PHP Tutorial

Php advanced, mysql database, php examples, php reference.

PHP is a server scripting language, and a powerful tool for making dynamic and interactive Web pages.

PHP is a widely-used, free, and efficient alternative to competitors such as Microsoft's ASP.

Easy Learning with "PHP Tryit"

With our online "PHP Tryit" editor, you can edit the PHP code, and click on a button to view the result.

Click on the "Try it Yourself" button to see how it works.

PHP Exercises

Test yourself with exercises.

Insert the missing part of the code below to output "Hello World".

Start the Exercise


Learn by examples! This tutorial supplements all explanations with clarifying examples.

See All PHP Examples

PHP Quiz Test

Learn by taking a quiz! This quiz will give you a signal of how much you know, or do not know, about PHP.

Start PHP Quiz!

My Learning

Track your progress with the free "My Learning" program here at W3Schools.

Log in to your account, and start earning points!

This is an optional feature. You can study at W3Schools without using My Learning.

how to write php documentation

PHP References

W3Schools' PHP reference contains different categories of all PHP functions, keywords and constants, along with examples.

PHP Exam - Get Your Diploma!

Kickstart your career.

Get certified by completing the course

Get Certified



Report Error

If you want to report an error, or if you want to make a suggestion, do not hesitate to send us an e-mail:

[email protected]

Top Tutorials

Top references, top examples, get certified.

WordPress Developer Resources

PHP Documentation Standards

In this article, documenting tips, formatting guidelines, 1. functions & class methods, 3. requires and includes, 4. hooks (actions and filters), 5. inline comments, 6. file headers, 7. constants, deprecated tags.

↑︎ Back to top

WordPress uses a customized documentation schema that draws inspiration from PHPDoc, an evolving standard for providing documentation to PHP code, which is maintained by phpDocumentor .

What Should Be Documented

PHP documentation in WordPress mostly takes the form of either formatted blocks of documentation or inline comments.

The following is a list of what should be documented in WordPress files:

  • Functions and class methods
  • Class members (including properties and constants)
  • Requires and includes
  • Hooks (actions and filters)
  • Inline comments
  • File headers

Summaries should be clear, simple, and brief. Avoid describing “why” an element exists, rather, focus on documenting “what” and “when” it does something.

A function, hook, class, or method is a third-person singular element, meaning that third-person singular verbs should be used to describe what each does.

  • Good : “(It) Does something.”
  • Bad : “(It) Do something.”

Summary examples:

  • Good: Displays the last modified date for a post.
  • Bad: Display the date on which the post was last modified.
  • Good: Filters the post content.
  • Bad: Lets you edit the post content that is output in the post template.
  • Good: _Fires after most of core is loaded, and the user is authenticated.
  • Bad: _Allows you to register custom post types, custom taxonomies, and other general housekeeping tasks after a lot of WordPress core has loaded.

Descriptive elements should be written as complete sentences. The one exception to this standard is file header summaries, which are intended as file “titles” more than sentences.

The serial (Oxford) comma should be used when listing elements in summaries, descriptions, and parameter or return descriptions.


@since : The recommended tool to use when searching for the version something was added to WordPress is svn blame . An additional resource for older hooks is the WordPress Hooks Database .

If the version number cannot be determined after using these tools, use @since Unknown .

Anything ported over from WPMU should use @since MU (3.0.0) . Existing @since MU (3.0.0) tags should not be changed.

Code Refactoring : It is permissible to space out the specific action or filter lines being documented to meet the coding standards, but do not refactor other code in the file.

DocBlocks should directly precede the hook, action, function, method, or class line. There should not be any opening/closing tags or other things between the DocBlock and the declarations to prevent the parser becoming confused.

No HTML markup or Markdown of any kind should be used in the summary. If the text refers to an HTML element or tag, then it should be written as “image tag” or “img” element, not “ <img> “. For example:

  • Good: Fires when printing the link tag in the header.
  • Bad: Fires when printing the <link> tag in the header.

Inline PHPDoc tags may be used.


HTML markup should never be used outside of code examples, though Markdown can be used, as needed, in the description.

Use a hyphen (-) to create an unordered list, with a blank line before and after.

Use numbers to create an ordered list, with a blank line before and after.

  • Code samples would be created by indenting every line of the code by 4 spaces, with a blank line before and after. Blank lines in code samples also need to be indented by four spaces. Note that examples added in this way will be output in <pre> tags and not syntax-highlighted. * Description including a code sample: * * $status = array( * 'draft' => __( 'Draft' ), * 'pending' => __( 'Pending Review' ), * 'private' => __( 'Private' ), * 'publish' => __( 'Published' ) * ); * * The description continues on ...
  • Links in the form of URLs, such as related Trac tickets or other documentation, should be added in the appropriate place in the DocBlock using the @link tag: * Description text. * * @link

@since Section (Changelogs)

Every function, hook, class, and method should have a corresponding @since version associated with it (more on that below).

No HTML should be used in the descriptions for @since tags, though limited Markdown can be used as necessary, such as for adding backticks around variables, arguments, or parameter names, e.g. $variable .

Versions should be expressed in the 3-digit x.x.x style:

If significant changes have been made to a function, hook, class, or method, additional @since tags, versions, and descriptions should be added to provide a changelog for that function.

“Significant changes” include but are not limited to:

  • Adding new arguments or parameters.
  • Required arguments becoming optional.
  • Changing default/expected behaviors.
  • Functions or methods becoming wrappers for new APIs.
  • Parameters which have been renamed (once PHP 8.0 support has been announced).

PHPDoc supports multiple @since versions in DocBlocks for this explicit reason. When adding changelog entries to the @since block, a version should be cited, and a description should be added in sentence case and form and end with a period:

Other Descriptions

@param , @type , @return : No HTML should be used in the descriptions for these tags, though limited Markdown can be used as necessary, such as for adding backticks around variables, e.g. $variable .

  • Hooks, e.g. 'save_post'
  • Dynamic hooks, e.g. '$old_status_to_$new_status' (Note that any extra curly braces have been removed inside the quotes)
  • Default or available values should use single quotes, e.g. ‘draft’. Translatable strings should be identified as such in the description.
  • HTML elements and tags should be written as “audio element” or “link tag”.

Line wrapping

DocBlock text should wrap to the next line after 80 characters of text. If the DocBlock itself is indented on the left 20 character positions, the wrap could occur at position 100, but should not extend beyond a total of 120 characters wide.

DocBlock Formatting

The examples provided in each section below show the expected DocBlock content and tags, as well as the exact formatting. Use spaces inside the DocBlock, not tabs, and ensure that items in each tag group are aligned according to the examples.

Functions and class methods should be formatted as follows:

  • Summary : A brief, one sentence explanation of the purpose of the function spanning a maximum of two lines. Use a period at the end.
  • Description : A supplement to the summary, providing a more detailed description. Use a period at the end of sentences.
  • @ignore : Used when an element is meant only for internal use and should be skipped from parsing.
  • @since x.x.x : Should always be 3-digit (e.g. @since 3.9.0 ). Exception is @since MU (3.0.0) .
  • @access : Only used for core-only functions or classes implementing “private” core APIs. If the element is private it will be output with a message stating its intention for internal use.
  • @see : Reference to a function, method, or class that is heavily-relied on within. See the note above about inline @see tags for expected formatting.
  • @link : URL that provides more information. This should never be used to reference another function, hook, class, or method, see @see .
  • @global : List PHP globals that are used within the function or method, with an optional description of the global. If multiple globals are listed, they should be aligned by type, variable, and description, with each other as a group.
  • @param : Note if the parameter is Optional before the description, and include a period at the end. The description should mention accepted values as well as the default. For example: Optional. This value does something. Accepts ‘post’, ‘term’, or empty. Default empty.
  • @return : Should contain all possible return types and a description for each. Use a period at the end. Note: @return void should not be used outside the default bundled themes and the PHP compatibility shims included in WordPress Core.

1.1 Parameters That Are Arrays

Parameters that are an array of arguments should be documented in the “originating” function only, and cross-referenced via an @see tag in corresponding DocBlocks.

Array values should be documented using WordPress’ flavor of hash notation style similar to how Hooks can be documented, each array value beginning with the @type tag, and taking the form of:

An example of an “originating” function and re-use of an argument array is wp_remote_request|post|get|head() .

In most cases, there is no need to mark individual arguments in a hash notation as optional , as the entire array is usually optional. Specifying “Optional.” in the hash notation description should suffice. In the case where the array is NOT optional, individual key/value pairs may be optional and should be marked as such as necessary.

1.2 Deprecated Functions

If the function is deprecated and should not be used any longer, the @deprecated tag, along with the version and description of what to use instead, should be added. Note the additional use of an @see tag – the Code Reference uses this information to attempt to link to the replacement function.

Class DocBlocks should be formatted as follows:

  • Summary : A brief, one sentence explanation of the purpose of the class spanning a maximum of two lines. Use a period at the end.
  • Description : A supplement to the summary, providing a more detailed description. Use a period at the end.

If documenting a sub-class, it’s also helpful to include an @see tag reference to the super class:

2.1 Class Members

2.1.1 properties.

Class properties should be formatted as follows:

  • Summary : Use a period at the end.
  • @var : Formatted the same way as @param , though the description may be omitted.

2.1.2 Constants

Files required or included should be documented with a summary description DocBlock. Optionally, this may apply to inline get_template_part() calls as needed for clarity.

Both action and filter hooks should be documented on the line immediately preceding the call to do_action() or do_action_ref_array() , or apply_filters() or apply_filters_ref_array() , and formatted as follows:

  • Summary : A brief, one line explanation of the purpose of the hook. Use a period at the end.
  • Description : A supplemental description to the summary, if warranted.
  • @ignore : Used when a hook is meant only for internal use and should be skipped from parsing.
  • @param : If the parameter is an array of arguments, document each argument using a hash notation (described above in the Parameters That Are Arrays section), and include a period at the end of each line.

Note that @return is not used for hook documentation, because action hooks return nothing, and filter hooks always return their first parameter.

If a hook is in the middle of a block of HTML or a long conditional, the DocBlock should be placed on the line immediately before the start of the HTML block or conditional, even if it means forcing line-breaks/PHP tags in a continuous line of HTML.

Tools to use when searching for the version a hook was added are svn blame , or the WordPress Hooks Database for older hooks. If, after using these tools, the version number cannot be determined, use @since Unknown .

4.1 Duplicate Hooks

Occasionally, hooks will be used multiple times in the same or separate core files. In these cases, rather than list the entire DocBlock every time, only the first-added or most logically-placed version of an action or filter will be fully documented. Subsequent versions should have a single-line comment.

For actions:

For filters:

To determine which instance should be documented, search for multiples of the same hook tag, then use svn blame to find the first use of the hook in terms of the earliest revision. If multiple instances of the hook were added in the same release, document the one most logically-placed as the “primary”.

Inline comments inside methods and functions should be formatted as follows:

5.1 Single line comments

5.2 multi-line comments.

Important note : Multi-line comments must not begin with /** (double asterisk) as the parser might mistake it for a DocBlock. Use /* (single asterisk) instead.

The file header DocBlock is used to give an overview of what is contained in the file.

Whenever possible, all WordPress files should contain a header DocBlock, regardless of the file’s contents – this includes files containing classes.

The Summary section is meant to serve as a succinct description of what specific purpose the file serves.

  • Good: “Widgets API: WP_Widget class”
  • Bad: “Core widgets class”

The Description section can be used to better explain overview information for the file such as how the particular file fits into the overall makeup of an API or component.

  • Good: “The Widgets API is comprised of the WP_Widget and WP_Widget_Factory classes in addition to a variety of top-level functionality that implements the Widgets and related sidebar APIs. WordPress registers a number of common widgets by default.”

The constant DocBlock is used to give a description of the constant for better use and understanding.

Constants should be formatted as follows:

  • @var : Formatted the same way as @param . The description is optional.

PHPDoc Tags

Common PHPDoc tags used in WordPress include @since , @see , @global @param , and @return (see table below for full list).

For the most part, tags are used correctly, but not all the time. For instance, sometimes you’ll see an @link tag inline, linking to a separate function or method. “Linking” to known classes, methods, or functions is not necessary, as the Code Reference automatically links these elements. For “linking” hooks inline, the proper tag to use is @see – see the Other Descriptions section.

The following text editors/IDEs have extensions/bundles you can install that will help you auto-create DocBlocks:

  • Notepad++: DocIt for Notepad++ (Windows)
  • TextMate: php.tmbundle (Mac)
  • SublimeText: sublime packages (Windows, Mac, Linux)
Preface: For the time being, and for the sake of consistency, WordPress Core will continue to use @subpackage tags – both when writing new DocBlocks, and editing old ones. Only when the new – external – PSR-5 recommendations are finalized, will across-the-board changes be considered, such as deprecating certain tags.

As proposed in the new PSR-5 recommendations, the following PHPDoc tag should be deprecated:

  • @subpackage (in favor of a unified package tag: @package Package\Subpackage )
  • @static (no longer needed)
  • @staticvar (no longer needed)

@package Tag in Plugins and Themes (bundled themes excluded)

Third-party plugin and theme authors must not use @package WordPress in their plugins or themes. The @package name for plugins should be the plugin name; for themes, it should be the theme name, spaced with underscores: Twenty_Fifteen .

@author Tag

It is WordPress’ policy not to use the @author tag, except in the case of maintaining it in external libraries. We do not want to imply any sort of “ownership” over code that might discourage contribution.

@copyright and @license Tags

The @copyright and @license tags are used in external libraries and scripts, and should not be used in WordPress core files.

  • @copyright is used to specify external script copyrights.
  • @license is used to specify external script licenses.
  • Wikipedia on PHPDoc
  • PEAR Standards
  • phpDocumentor
  • phpDocumentor Tutorial Tags
  • Draft PSR-5 recommendations
  • Draft PSR-19 recommendations

First published

Last updated

Edit article

Improve it on GitHub : PHP Documentation Standards”

See list of changes : PHP Documentation Standards”

  • phpDocumentor 2
  • phpDocumentor 1

Table Of Contents

  • Which elements can be documented?
  • What does a DocBlock look like?
  • Running phpDocumentor

Previous topic

Changing the Look and Feel

  • Homepage »
  • Documentation »
  • Getting started »

Your First Set of Documentation ¶

The goal of this tutorial is to introduce you in writing and subsequently generating effective documentation with phpDocumentor.

Writing a DocBlock ¶

A DocBlock is a piece of inline documentation in your source code that informs you what a class, method or other Structural Element its function is.

Which elements can be documented? ¶

Before we discuss what a DocBlock looks like, let’s first zoom into what you can document with them. phpDocumentor follows the PHPDoc definition and recognizes the following Structural Elements :

  • Class constant

In addition to the above the PHPDoc standard also supports DocBlocks for Files and include/require statements, even though PHP itself does not know this concept.

Each of these elements can have exactly one DocBlock associated with it, which directly precedes it. No code or comments may be between a DocBlock and the start of an element’s definition.

What does a DocBlock look like? ¶

DocBlocks are always enclosed in a comment-type, called DocComment , that starts with /** and ends with */ . Each line in between the opening and closing statement should start with an asterisk ( * ). Every DocBlock precedes exactly one Structural Element and all contents of the DocBlock apply to that associated element.

For example:

File-level DocBlocks

Quite often projects will want to document the license or function for an entire file instead of a single element. This can be accomplished by having a DocBlock as the first element encountered in a file. It is important to note that whenever another Structural Element directly follows the DocBlock that it is no longer recognized as a File-level DocBlock but belonging to the subsequent element.

The following DocBlock is a File-level DocBlock:

However in the following example the DocBlock belongs to the class:

DocBlocks are divided into the following three parts. Each of these parts is optional, except that a Description may not exist without a Summary .

Sometimes called a short description, provides a brief introduction into the function of the associated element. A Summary ends in one of these situations:

A dot is following by a line break, or Two subsequent line breaks are encountered.

A DocBlock looks like this:

Let’s go through this example line by line and discuss which is which,

If you’d like to know more about what DocBlocks do for you, visit the chapter Inside DocBlocks for more in-depth information.

Running phpDocumentor ¶

After you have installed phpDocumentor you can use the phpdoc command to generate your documentation.

In this document we expect that the phpdoc command is available; thus whenever we ask you to run a command it would be in the following form:

When you have installed a version via composer or manually you should invoke the phpdoc script in the bin folder of your phpDocumentor installation.

Under Linux / MacOSX that would be:

And under Windows that would be:

The basic usage of phpDocumentor is to provide an input location using the command line options ( -d for a directory, -f for a file) and tell it to output your documentation to a folder of your liking ( -t ).

What the above example does is scan all files in the src directory and its subdirectories, perform an analysis and generate a website containing the documentation in the folder docs/api . If you want you can even omit the -t option, in which case the output will be written to a subfolder called output .

phpDocumentor features several templates with which you can change the appearance of your documentation. See the chapter Changing the Look and Feel for more information on how to switch between templates.

There are a lot more options to phpDocumentor and you can define them all in a Configuration file and include that in your project but that is out of scope for this tutorial. If you’d like to know more on running phpDocumentor; see the guide on Running phpDocumentor for more information.

  • Getting Started

A simple tutorial

Table of contents.

  • What do I need?
  • Your first PHP-enabled page
  • Something Useful
  • Dealing with Forms
  • What's next?

Here we would like to show the very basics of PHP in a short, simple tutorial. This text only deals with dynamic web page creation with PHP, though PHP is not only capable of creating web pages. See the section titled What can PHP do for more information.

PHP-enabled web pages are treated just like regular HTML pages and you can create and edit them the same way you normally create regular HTML pages.

User Contributed Notes

To Top

PHPDocs Basics

  • PHPDoc Types
  • Solving Undefined Variables
  • Narrowing Types
  • Config Reference
  • Developing Extensions

PHPDocs are a big part of what makes PHPStan work. PHP in its most recent versions can express a lot of things in the native typehints, but it still leaves a lot of room for PHPDocs to augment the information.

Valid PHPDocs start with /** . Variants starting only with /* or line comments // are not considered PHPDocs. [1]

Learn more about PHPDoc types » you can use in the tags described below.

Would you like to fix incorrect PHPDocs in 3 rd party code you have in /vendor? You can! Check out Stub Files »

Methods and functions #

This is how a valid PHPDoc above a function or a method can look like:

Properties #

PHPDocs can be written above class properties to denote their type:

Inline @var #

Casting a type using an inline @var PHPDocs should be used only as a last resort. It can be used in a variable assignment like this:

This is usually done if the symbol on the right side of the = operator has a wrong type, or isn’t specific enough. Usage of inline @var is problematic for a couple of reasons:

  • Because it might be used to correct wrong type information of the called symbol, PHPStan always trusts it. But if there’s a mistake in this annotation, the analysis of the code below might be wrong.
  • The inline @var needs to be repeated above all usages of the symbol which leads to repetition in the codebase.

Instead, the type should be fixed at its source. If the called symbol comes from 3rd party code, you can correct it using a stub file . If the return type differs in each call based on the passed arguments, you can use generics , or write a dynamic return type extension instead.

If you really need to use an inline @var , consider an alternative - an assert() call, which can throw an exception at runtime, so the code execution doesn’t continue if the requirements aren’t met.

Magic properties #

For custom __get / __set methods logic, a @property PHPDoc tag can be placed above a class. If the property is only supposed to be read or written to, @property-read / @property-write variants can be used.

The @property tag can also be used to override wrong property type from a parent class.

Magic methods #

For custom __call methods logic, a @method PHPDoc tag can be placed above a class:

When a class delegates unknown method calls and property accesses to a different class using __call and __get / __set , we can describe the relationship using @mixin PHPDoc tag:

It also works with generics :

Combining PHPDoc types with native typehints #

PHPDocs can also complement native typehints with additional information. The most common use-case is telling PHPStan what’s in an array:

You can also use an alternative array<User> syntax, or even specify the key type:

More about this in PHPDoc Types > Iterables .

Using @return static along with the self native typehint means that the method returns a child class ( see example ):

A narrower @return $this instead of @return static can also be used, and PHPStan will check if you’re really returning the same object instance and not just the child class.

Variadic functions #

This allows specifying functions or methods which have a variable amount of parameters (available since PHP 5.6 ).

Your code can look like this:

PHPDoc tags @template , @template-covariant , @template-contravariant , @extends , @implements , and @use are reserved for generics. Learn more about generics » , covariance » , contravariance » , and type projections » . Also check out Generics By Examples » .

Narrowing types after function call #

PHPDoc tags @phpstan-assert , @phpstan-assert-if-true , @phpstan-assert-if-false are used to inform PHPStan about type-narrowing happening inside called functions and methods. Learn more »

Setting parameter type passed by reference #

PHPDoc tag @param-out can be used to set a parameter type passed by reference:

Change type of current object after calling a method #

PHPDoc tags @phpstan-self-out or @phpstan-this-out can be used to change the type of the current object after calling a method on it. This is useful for generic mutable objects.

Deprecations #

Use @deprecated tag to mark declarations as deprecated:

Install phpstan-deprecation-rules extension to have usages of deprecated symbols reported.

The @deprecated PHPDoc tag is inherited to implicitly mark overridden methods in child classes also as deprecated:

To break the inheritance chain and un-mark Bar::doFoo() as deprecated, use @not-deprecated PHPDoc tag:

Impure functions #

By default, PHPStan considers all functions that return a value to be pure . That means that a second call to the same function in the same scope will return the same narrowed type. If you have a function that may return different values on successive calls based on a global state like a random number generator, database, or time, then the function is impure. You can tell PHPStan about impure functions and methods with the @phpstan-impure tag:

The @phpstan-pure tag is also available should you need it, for example if you’ve set rememberPossiblyImpureFunctionValues: false in your configuration file (available in PHPStan 1.8.0). See Config Reference for more details.

Enforcing class inheritance for interfaces and traits #

PHPDoc tag @phpstan-require-extends can be put above interfaces and traits. When this interface is implemented or trait is used by a class, this class has to extend a parent declared by this tag.

This is useful for solving “Access to an undefined property” error when trying to access a property declared by PHPDoc tag @property on an interface on PHP 8.2+. Learn more »

Enforcing implementing an interface for traits #

PHPDoc tag @phpstan-require-implements can be put above traits. When this trait is used by a class, this class has to implement an interface declared by this tag.

Prefixed tags #

Supported tags ( @var , @param , @return , and all generics-related ones ) can be prefixed with @phpstan- :

This is useful in the context of advanced types and generics . IDEs and other PHP tools might not understand the advanced types that PHPStan takes advantage of. So you can leave the ordinary @param in the PHPDoc and add a @phpstan-param with an advanced type syntax.

Classes named after internal PHP types #

When having classes named like Resource , Double , Number (or Mixed until PHP 8), there is no possible way to distinguish between either the PHP internal type or the custom class to use in the PHPDoc. By default, PHPStan will consider the type as being the PHP internal type, which means some false-positives can appear.

To make PHPStan understand the passed argument must be an instance of a Resource object, use a fully-qualified name in the PHPDoc. PHPStan will understand that as the object of My\Resource class.

Readonly properties #

PHPStan supports native PHP 8.1 readonly properties and validates their correct usage. For older PHP versions, PHPStan also understands the @readonly PHPDoc tag to apply similar rules.

This feature needs to be enabled via feature toggle by opting in to bleeding edge .

Immutable classes #

@immutable on the class can be used to make PHPStan treat every property of that class as being readonly.

Only the /** style comments are supported because they’re represented with different tokens ( T_DOC_COMMENT ) by the PHP parser and only this token type is supposed to represent a PHPDoc. ↩︎

Edit this page on GitHub

Introduction to PhpDoc

Moshe Teutsch

If you’ve ever tried to read code written by someone other than yourself (who hasn’t?), you know it can be a daunting task. A jumble of “spaghetti code” mixed with numerous oddly named variables makes your head spin. Does this function expect a string or an array? Does this variable store an integer or an object? After countless hours of following the threads of code and trying to understand what each bit does, it’s not uncommon to give up and just rewrite the whole thing from scratch – a task that wastes far too much of your precious time. PhpDoc, short for PhpDocumentor, is a powerful tool that allows you to easily document your code via specially formatted comments. The documentation will be available not only in the source code, but also in professional documentation extracted using either the web or command-line interface. The result can be in various formats such as HTML, PDF, and CHM. Additionally, many IDEs that provide code-completion can parse PhpDoc comments and provide useful features such as type-hinting. By using PhpDoc, you can make it easy for others (and yourself) to understand your code – weeks, months, and even years after you’ve written it. The easiest way to install PhpDoc is with PEAR. Of course, before you can do so you must have PEAR installed. If you don’t, follow the instructions at . In this article I’ll show you how to use PhpDoc to generate gorgeous and user-friendly documentation from beginning to end.

What Can I Document?

Functions and methods.

  • Class properties
  • Global variables
  • include() / require()

Generating Documentation

Frequently asked questions (faqs) about phpdoc, what is the significance of phpdoc in php programming.

PHPDoc is a documentation tool in PHP programming that allows developers to provide information about the functionality of their code in a standardized format. It is a powerful tool that helps in understanding the code better, making it easier to maintain and debug. PHPDoc comments are written directly in the source code, making them readily available and easy to update. They can describe functions, classes, methods, constants, and more. PHPDoc also supports generating API documentation in HTML format, which can be shared with other developers or end-users.

How do I write a basic PHPDoc comment?

Writing a PHPDoc comment is straightforward. It starts with a “/**” and ends with a “*/”. Inside this, you can include various tags to describe different aspects of your code. For example, the “@param” tag is used to describe a function parameter, and the “@return” tag is used to describe the return value of a function. Here’s an example: /** * Calculates the sum of two numbers. * * @param int $a The first number. * @param int $b The second number. * @return int The sum of the two numbers. */ function sum($a, $b) { return $a + $b; }

Can I generate documentation from PHPDoc comments?

Yes, one of the key features of PHPDoc is its ability to generate API documentation from your comments. This is done using a tool like phpDocumentor, which scans your source code and generates HTML pages containing your comments and information about your code’s structure. This can be extremely useful for sharing information about your code with other developers or end-users.

What are some common PHPDoc tags and their uses?

PHPDoc supports a wide range of tags to describe different aspects of your code. Some of the most common ones include “@param” (describes function parameters), “@return” (describes the return value of a function), “@var” (describes a variable), “@throws” (indicates the exceptions a function can throw), and “@deprecated” (indicates that a piece of code is deprecated and should not be used).

How can PHPDoc help with code quality and debugging?

PHPDoc can significantly improve code quality and ease the debugging process. By providing detailed information about your code’s functionality, PHPDoc comments make it easier to understand what each part of your code is supposed to do. This can help prevent bugs and make it easier to spot any that do occur. Additionally, many IDEs can use PHPDoc comments to provide autocompletion and other helpful features, further improving your productivity.

Can PHPDoc comments include examples?

Yes, PHPDoc comments can include examples of how to use a function or method. This can be done using the “@example” tag, followed by the path to a file containing the example code. This can be a great way to provide additional context and help other developers understand how to use your code.

How does PHPDoc handle inheritance?

PHPDoc has built-in support for inheritance. If a class extends another class, PHPDoc will automatically include the parent class’s comments in the child class’s documentation, unless the child class has its own comments. This can be a great way to avoid duplicating information and keep your documentation consistent.

Can PHPDoc comments be used with private and protected methods?

Yes, PHPDoc comments can be used with private and protected methods, as well as public ones. However, keep in mind that private and protected methods are not included in the generated documentation by default, as they are not part of the public API. If you want to include them, you’ll need to configure your documentation generator accordingly.

What is the difference between PHPDoc and other documentation tools?

PHPDoc is specifically designed for PHP and supports features specific to the language, such as namespaces and traits. It also supports a wide range of tags to describe different aspects of your code, making it a very flexible tool. Other documentation tools may not have these features, or they may be designed for different programming languages.

How can I get started with PHPDoc?

To get started with PHPDoc, you’ll first need to understand how to write PHPDoc comments. Once you’re comfortable with that, you can start adding them to your code. From there, you can use a tool like phpDocumentor to generate documentation from your comments. Remember, the key to good documentation is to keep it up-to-date and as detailed as possible.

How to create effective PHP project documentation with Read the Docs

Documentation is one of the ways that software projects can communicate information to their users. Effective documentation is high-quality, meaning that it’s complete, accurate, and up-to-date. At least for open source libraries, it also means that you can find it with a search engine. For many small PHP projects, the reality is very far removed from the ideal.

Read the Docs ( ) makes it easy to host an up-to-date copy of your project’s documentation online. There are around 2,000 PHP projects which host their documentation on the site, which makes PHP the third most popular programming language for projects on the site.

This post covers the process that is used to automatically publish the documentation for the gfx-php PHP graphics library, which is one of those 2000 projects. You should consider using this setup as a template if you your project is small enough that it does not have its own infrastructure.

how to write php documentation

Basic concept

Typically, people are using Read the Docs with a tool called Sphinx. If you are writing in Python, it’s also possible to use the autodoc Sphinx plugin to add API documentation, based on docstrings in the code.

PHP programmers are already spoiled for choice if they want to produce HTML documentation from their code. These tools all have huge PHP user bases:

  • phpDocumentor

These will each output their own HTML, which is only useful if you want to self-host the documentation. I wanted a tool that was more like “autodoc for PHP”, so that I can have my API docs magically appear in Sphinx output that is hosted on Read the Docs.

Doxygen is the most useful tool for this purpose, because it has a stable XML output format and good-enough PHP support. I decided to write a tool which to take the Doxygen XML info and generate rest for Sphinx:

This introduces some extra tools, which looks complex at first. The stack is geared towards running within the Read the Docs build environment, so most developers can treat it as a black box after the initial setup:

This setup is entirely hosted with free cloud services, so you don’t need to run any applications on your own hardware.

Tools to install on local workstation

First, we will set up each of these tools locally, so that we know everything is working before we upload it.


Doxygen can read PHP files to extract class names, documentation and method signatures. Linux and Mac install this from most package managers ( apt-get , dnf or brew ) under the name doxygen , while Windows users need to chase down binaries.

In your repo, make a sub-folder called docs/ , and create a Doxyfile with some defaults:

You need to edit the configuration to make it suitable or generating XML output for your PHP project. The version of Doxygen used here is 1.8.13, where you only need to change a few values to set Doxygen to:

  • Recursively search PHP files in your project’s source folder
  • Generate XML and HTML only
  • Log warnings to a file

For a typical project, these settings are:

Once you set these in Doxyfile , you can run Doxygen to generate HTML and XML output.

Doxygen will pick up most method signatures automatically, and you can add to them via docblocks , which work along the same lines as docstrings in Python. Read Doxygen: Documenting the Code to learn the syntax if you have not used a documentation generator in a curly-bracket language before.

The Doxygen HTML will never be published, but you might need to read it to see how well Doxygen understands your code.

how to write php documentation

The XML output is much more useful for our purposes. It contains the same information, and we will read it to generate pages of documentation for Sphinx to render.

how to write php documentation

Sphinx is the tool that we will use to render the final HTML output. If you haven’t used it before, then see the official Getting Started page.

We are using Sphinx because it can be executed by online services like Read the Docs. It uses the reStructuredText format, which is a whole lot more complex than Markdown, but supports cross-references. I’ll only describe these steps briefly, because there are existing how-to guides on making Sphinx work for manually-written PHP documentation elsewhere on the Internet, such as:

  • Using Sphinx for PHP Project Documentation .
  • Sphinx PHPdomain released

Still in the docs folder with your Doxyfile, create and render an empty Sphinx project.

The generated HTML will initially appear like this:

how to write php documentation

We need to customize this in a way that adds PHP support. The quickest way is to drop this text into requirements.txt :

Then these two sections of :

Add this to the end of

And drop this contents in _templates/breadcrumbs.html ( explanation )

Then finally re-install dependencies and re-build:

The HTML output under _build will now appear as:

how to write php documentation

This setup gives us three things:

  • The documentation looks the same as Read the Docs.
  • We can use PHP snippets and class documentation.
  • There are no ‘Edit’ links, which is important because some of the files will be generated in the next steps.

The doxyphp2sphinx tool will generate .rst files from the Doxygen XML files. This was installed from your requirements.txt in the last step, but you can also install it standalone via pip:

The only thing you need to specify is the name of the namespace that you are documenting, using :: as a separator.

This command will read the xml/ subdirectory, and will create api.rst . It will fill the api/ directory with documentation for each class in the \FooCorp\Example namespace.

To verify that this has worked, check your class structure:

You should have documentation for each of these:

And if you have the correct namespace name, you will have .rst files for each as well:

Now, add a reference to api.rst somewhere in index.rst :

And re-compile:

You can now navigate to your classes in the HTML documentation.

how to write php documentation

The quality of the generated class documentation can be improved by adding docstrings. An example of the generated documentation for a method is:

how to write php documentation

Writing documentation

As you add pages to your documentation, you can include PHP snippets and reference the usage of your classes.

This will create syntax highlighting for your examples and inline links to the generated API docs.

how to write php documentation

Beyond this, you will need to learn some reStructuredText. I found this reference to be useful.

Local docs build

A full build has these dependencies:

And these steps:

Cloud tools

Next, we will take this local build, and run it on a cloud setup instead, using these services.

  • Read the docs

I will assume that you know how to use Git and GitHub, and that you are creating code that is intended for re-use.

Add these files to your .gitignore :

Upload the remainder of your repository to GitHub. The gfx-php project is an example of a working project with all of the correct files included.

To have the initial two build steps execute on Read the Docs, add this to the end of docs/ . Don’t forget to update the namespace to match the command you were running locally.

Read the Docs

After all this setup, Read the Docs should be able to build the project. Create the project on Read the Docs by using the Import from GitHub option. There are only two settings which need to be set:

The requirements file location must be docs/requirements.txt :

how to write php documentation

And the programming language should be PHP.

how to write php documentation

After this, you can go ahead and run a build.

As a last step, you will want to ensure that you have a Webhook set up on GitHub to trigger the builds automatically in future.

how to write php documentation

It is emerging as a best practice for small libraries to host their documentation with Read the Docs, but this is not yet common in the PHP world. Larger PHP projects tend to self-host documentation on the project website, but smaller projects will often have no hosted API documentation.

Once you write your docs, publishing them should be easy! Hopefully this provides a good example of what’s possible.


Credit where credit is due: The Breathe project fills this niche for C++ developers using Doxygen, and has been around for some time. Breathe is in the early stages of adding PHP support, but is not yet ready at the time of writing.

Leave a Reply

Your email address will not be published. Required fields are marked *

Notify me of follow-up comments by email.

Notify me of new posts by email.

The PHP Handbook – Learn PHP for Beginners

PHP is an incredibly popular programming language.

Statistics say it’s used by 80% of all websites. It’s the language that powers WordPress, the widely used content management system for websites.

And it also powers a lot of different frameworks that make Web Development easier, like Laravel. Speaking of Laravel, it may be one of the most compelling reasons to learn PHP these days.

Why Learn PHP?

PHP is quite a polarizing language. Some people love it, and some people hate it. If we move a step above the emotions and look at the language as a tool, PHP has a lot to offer.

Sure it’s not perfect. But let me tell you – no language is.

In this handbook, I’m going to help you learn PHP.

This book is a perfect introduction if you’re new to the language. It’s also perfect if you’ve done “some PHP” in the past and you want to get back to it.

I’ll explain modern PHP, version 8+.

PHP has evolved a lot in the last few years. So if the last time you tried it was PHP 5 or even PHP 4, you’ll be surprised at all the good things that PHP now offers.

Here's what we'll cover in this handbook:

Introduction to PHP

What kind of language is php, how to setup php, how to code your first php program, php language basics, how to work with strings in php, how to use built-in functions for numbers in php, how arrays work in php, how conditionals work in php, how loops work in php, how functions work in php, how to loop through arrays with map() , filter() , and reduce() in php, object oriented programming in php, how to include other php files, useful constants, functions and variables for filesystem in php, how to handle errors in php, how to handle exceptions in php, how to work with dates in php, how to use constants and enums in php, how to use php as a web app development platform, how to use composer and packagist, how to deploy a php application.

Note that you can get a PDF, ePub, or Mobi version of this handbook for easier reference, or for reading on your Kindle or tablet.

PHP is a programming language that many devs use to create Web Applications, among other things.

As a language, it had a humble beginning. It was first created in 1994 by Rasmus Lerdorf to build his personal website. He didn’t know at the time it would eventually become one of the most popular programming languages in the world. It became popular later on, in 1997/8, and exploded in the 2000s when PHP 4 landed.

You can use PHP to add a little interactivity to an HTML page.

Or you can use it as a Web Application engine that creates HTML pages dynamically and sends them to the browser.

It can scale to millions of page views.

Did you know Facebook is powered by PHP? Ever heard of Wikipedia? Slack? Etsy?

Let’s get into some technical jargon.

Programming languages are divided into groups depending on their characteristics. For example interpreted/compiled, strongly/loosely typed, dynamically/statically typed.

PHP is often called a “scripting language” and it’s an interpreted language . If you’ve used compiled languages like C or Go or Swift, the main difference is that you don’t need to compile a PHP program before you run it.

Those languages are compiled and the compiler generates an executable program that you then run. It’s a 2-steps process.

The PHP interpreter is responsible for interpreting the instructions written in a PHP program when it’s executed. It’s just one step. You tell the interpreter to run the program. It's a completely different workflow.

PHP is a dynamically typed language . The types of variables are checked at runtime, rather than before the code is executed as happens for statically typed languages. (These also happen to be compiled – the two characteristics often go hand in hand.)

PHP is also loosely (weakly) typed. Compared to strongly typed languages like Swift, Go, C or Java, you don’t need to declare the types of your variables.

Being interpreted and loosely/dynamically typed will make bugs harder to find before they happen at runtime.

In compiled languages, you can often catch errors at compile time, something that does not happen in interpreted languages.

But on the other hand, an interpreted language has more flexibility.

Fun fact: PHP is written internally in C, a compiled and statically typed language.

In its nature, PHP is similar to JavaScript, another dynamically typed, loosely typed, and interpreted language.

PHP supports object-oriented programming, and also functional programming. You can use it as you prefer.

There are many ways to install PHP on your local machine.

The most convenient way I’ve found to install PHP locally is to use MAMP.

MAMP is a tool that’s freely available for all the Operating Systems – Mac, Windows and Linux. It is a package that gives you all the tools you need to get up and running.

PHP is run by a HTTP Server, which is responsible for responding to HTTP requests, the ones made by the browser. So you access a URL with your browser, Chrome or Firefox or Safari, and the HTTP server responds with some HTML content.

The server is typically Apache or NGINX.

Then to do anything non-trivial you’ll need a database, like MySQL.

MAMP is a package that provides all of that, and more, and gives you a nice interface to start/stop everything at once.

Of course, you can set up each piece on its own if you like, and many tutorials explain how to do that. But I like simple and practical tools, and MAMP is one of those.

You can follow this handbook with any kind of PHP installation method, not just MAMP.

That said, if you don’t have PHP installed yet and you want to use MAMP, go to and install it.

The process will depend on your operating system, but once you’re done with the installation, you will have a “MAMP” application installed.

Start that, and you will see a window similar to this:

Screen Shot 2022-06-24 at 15.14.05.jpg

Make sure the PHP version selected is the latest available.

At the time of writing MAMP lets you pick 8.0.8.

NOTE: I noticed MAMP has a version that’s a bit behind, not the latest. You can install a more recent version of PHP by enabling the MAMP PRO Demo, then install the latest release from the MAMP PRO settings (in my case it was 8.1.0). Then close it and reopen MAMP (non-pro version). MAMP PRO has more features so you might want to use it, but it’s not necessary to follow this handbook.

Press the Start button at the top right. This will start the Apache HTTP server, with PHP enabled, and the MySQL database.

Go to the URL http://localhost:8888 and you will see a page similar to this:

Screen Shot 2022-06-24 at 15.19.05.jpg

We’re ready to write some PHP!

Open the folder listed as “Document root”. If you're using MAMP on a Mac it’s by default /Applications/MAMP/htdocs .

On Windows it’s C:\MAMP\htdocs .

Yours might be different depending on your configuration. Using MAMP you can find it in the user interface of the application.

In there, you will find a file named index.php .

That is responsible for printing the page shown above.

Screen Shot 2022-06-24 at 15.17.58.jpg

When learning a new programming language we have this tradition of creating a “Hello, World!” application. Something that prints those strings.

Make sure MAMP is running, and open the htdocs folder as explained above.

Open the index.php file in a code editor.

I recommend using VS Code , as it’s a very simple and powerful code editor. You can check out for an introduction.

Screen Shot 2022-06-24 at 15.37.36.jpg

This is the code that generates the “Welcome to MAMP” page you saw in the browser.

Delete everything and replace it with:

Save, refresh the page on http://localhost:8888 , you should see this:

Screen Shot 2022-06-24 at 15.39.00.jpg

Great! That was your first PHP program.

Let’s explain what is happening here.

We have the Apache HTTP server listening on port 8888 on localhost, your computer.

When we access http://localhost:8888 with the browser, we’re making an HTTP request, asking for the content of the route / , the base URL.

Apache, by default, is configured to serve that route serving the index.html file included in the htdocs folder. That file does not exist – but as we have configured Apache to work with PHP, it will then search for an index.php file.

This file exists, and PHP code is executed server-side before Apache sends the page back to the browser.

In the PHP file, we have a <?php opening, which says “here starts some PHP code”.

We have an ending ?> that closes the PHP code snippet, and inside it, we use the echo instruction to print the string enclosed into quotes into the HTML.

A semicolon is required at the end of every statement.

We have this opening/closing structure because we can embed PHP inside HTML. PHP is a scripting language, and its goal is to be able to “decorate” an HTML page with dynamic data.

Note that with modern PHP, we generally avoid mixing PHP into the HTML. Instead, we use PHP as a “framework to generate the HTML” – for example using tools like Laravel. But we'll discuss plain PHP in this book, so it makes sense to start from the basics.

For example, something like this will give you the same result in the browser:

To the final user, who looks at the browser and has no idea of the code behind the scenes, there’s no difference at all.

The page is technically an HTML page, even though it does not contain HTML tags but just a Hello World string. But the browser can figure out how to display that in the window.

After the first “Hello World”, it’s time to dive into the language features with more details.

How Variables Work in PHP

Variables in PHP start with the dollar sign $ , followed by an identifier, which is a set of alphanumeric chars and the underscore _ char.

You can assign a variable any type of value, like strings (defined using single or double quotes):

Or numbers:

or any other type that PHP allows, as we’ll later see.

Once a variable is assigned a value, for example a string, we can reassign it a different type of value, like a number:

PHP won’t complain that now the type is different.

Variable names are case-sensitive. $name is different from $Name .

It’s not a hard rule, but generally variable names are written in camelCase format, like this: $brandOfCar or $ageOfDog . We keep the first letter lowercase, and the letters of the subsequent words uppercase.

How to Write Comments in PHP

A very important part of any programming language is how you write comments.

You write single-line comments in PHP in this way:

Multi-line comments are defined in this way:

What are Types in PHP?

I mentioned strings and numbers.

PHP has the following types:

  • bool boolean values (true/false)
  • int integer numbers (no decimals)
  • float floating-point numbers (decimals)
  • string strings
  • array arrays
  • object objects
  • null a value that means “no value assigned”

and a few other more advanced ones.

How to Print the Value of a Variable in PHP

We can use the var_dump() built-in function to get the value of a variable:

The var_dump($name) instruction will print string(6) "Flavio" to the page, which tells us the variable is a string of 6 characters.

If we used this code:

we’d have int(20) back, saying the value is 20 and it’s an integer.

var_dump() is one of the essential tools in your PHP debugging tool belt.

How Operators Work in PHP

Once you have a few variables you can make operations with them:

The * I used to multiply $base by $height is the multiplication operator.

We have quite a few operators – so let’s do a quick roundup of the main ones.

To start with, here are the arithmetic operators: + , - , * , / (division), % (remainder) and ** (exponential).

We have the assignment operator = , which we already used to assign a value to a variable.

Next up we have comparison operators, like < , > , <= , >= . Those work like they do in math.

== returns true if the two operands are equal.

=== returns true if the two operands are identical.

What’s the difference?

You’ll find it with experience, but for example:

We also have != to detect if operands are not equal:

and !== to detect if operands are not identical:

Logical operators work with boolean values:

We also have the not operator:

I used the boolean values true and false here, but in practice you’ll use expressions that evaluate to either true or false, for example:

All of the operators listed above are binary , meaning they involve 2 operands.

PHP also has 2 unary operators: ++ and -- :

I introduced the use of strings before when we talked about variables and we defined a string using this notation:

The big difference between using single and double quotes is that with double quotes we can expand variables in this way:

and with double quotes we can use escape characters (think new lines \n or tabs \t ):

PHP offers you a very comprehensive functions in its standard library (the library of functionalities that the language offers by default).

First, we can concatenate two strings using the . operator:

We can check the length of a string using the strlen() function:

This is the first time we've used a function.

A function is composed of an identifier ( strlen in this case) followed by parentheses. Inside those parentheses, we pass one or more arguments to the function. In this case, we have one argument.

The function does something and when it’s done it can return a value. In this case, it returns the number 6 . If there’s no value returned, the function returns null .

We’ll see how to define our own functions later.

We can get a portion of a string using substr() :

We can replace a portion of a string using str_replace() :

Of course we can assign the result to a new variable:

There are a lot more built-in functions you can use to work with strings.

Here is a brief non-comprehensive list just to show you the possibilities:

  • trim() strips white space at the beginning and end of a string
  • strtoupper() makes a string uppercase
  • strtolower() makes a string lowercase
  • ucfirst() makes the first character uppercase
  • strpos() finds the firsts occurrence of a substring in the string
  • explode() to split a string into an array
  • implode() to join array elements in a string

You can find a full list here .

I previously listed the few functions we commonly use for strings.

Let’s make a list of the functions we use with numbers:

  • round() to round a decimal number, up/down depending if the value is > 0.5 or smaller
  • ceil() to round a a decimal number up
  • floor() to round a decimal number down
  • rand() generates a random integer
  • min() finds the lowest number in the numbers passed as arguments
  • max() finds the highest number in the numbers passed as arguments
  • is_nan() returns true if the number is not a number

There are a ton of different functions for all sorts of math operations like sine, cosine, tangents, logarithms, and so on. You can find a full list here .

Arrays are lists of values grouped under a common name.

You can define an empty array in two different ways:

An array can be initialized with values:

Arrays can hold values of any type:

Even other arrays:

You can access the element in an array using this notation:

Once an array is created, you can append values to it in this way:

You can use array_unshift() to add the item at the beginning of the array instead:

Count how many items are in an array using the built-in count() function:

Check if an array contains an item using the in_array() built-in function:

If in addition to confirming existence, you need the index, use array_search() :

Useful Functions for Arrays in PHP

As with strings and numbers, PHP provides lots of very useful functions for arrays. We’ve seen count() , in_array() , array_search() – let’s see some more:

  • is_array() to check if a variable is an array
  • array_unique() to remove duplicate values from an array
  • array_search() to search a value in the array and return the key
  • array_reverse() to reverse an array
  • array_reduce() to reduce an array to a single value using a callback function
  • array_map() to apply a callback function to each item in the array. Typically used to create a new array by modifying the values of an existing array, without altering it.
  • array_filter() to filter an array to a single value using a callback function
  • max() to get the maximum value contained in the array
  • min() to get the minimum value contained in the array
  • array_rand() to get a random item from the array
  • array_count_values() to count all the values in the array
  • implode() to turn an array into a string
  • array_pop() to remove the last item of the array and return its value
  • array_shift() same as array_pop() but removes the first item instead of the last
  • sort() to sort an array
  • rsort() to sort an array in reverse order
  • array_walk() similarly to array_map() does something for every item in the array, but in addition it can change values in the existing array

How to Use Associative Arrays in PHP

So far we’ve used arrays with an incremental, numeric index: 0, 1, 2…

You can also use arrays with named indexes (keys), and we call them associative arrays:

We have some functions that are especially useful for associative arrays:

  • array_key_exists() to check if a key exists in the array
  • array_keys() to get all the keys from the array
  • array_values() to get all the values from the array
  • asort() to sort an associative array by value
  • arsort() to sort an associative array in descending order by value
  • ksort() to sort an associative array by key
  • krsort() to sort an associative array in descending order by key

You can see all array-related functions here .

I previously introduced comparison operators: < , > , <= , >= , == , === , != , !== ... and so on.

Those operators are going to be super useful for one thing: conditionals .

Conditionals are the first control structure we see.

We can decide to do something, or something else, based on a comparison.

For example:

The code inside the parentheses only executes if the condition evaluates to true .

Use else to do something else in case the condition is false :

NOTE: I used cannot instead of can't because the single quote would terminate my string before it should. In this case you could escape the ' in this way: echo 'You can\'t enter the pub';

You can have multiple if statements chained using elseif :

In addition to if , we have the switch statement.

We use this when we have a variable that could have a few different values, and we don’t have to have a long if / elseif block:

I know the example does not have any logic, but I think it can help you understand how switch works.

The break; statement after each case is essential. If you don’t add that and the age is 17, you’d see this:

Instead of just this:

as you’d expect.

Loops are another super useful control structure.

We have a few different kinds of loops in PHP: while , do while , for , and foreach .

Let’s see them all!

How to Use a while loop in PHP

A while loop is the simplest one. It keeps iterating while the condition evaluates to true :

This would be an infinite loop, which is why we use variables and comparisons:

How to Use a do while loop in PHP

do while is similar, but slightly different in how the first iteration is performed:

In the do while loop, first we do the first iteration, then we check the condition.

In the while loop, first we check the condition, then we do the iteration.

Do a simple test by setting $counter to 15 in the above examples, and see what happens.

You'll want to choose one kind of loop, or the other, depending on your use case.

How to Use a foreach Loop in PHP

You can use the foreach loop to easily iterate over an array:

You can also get the value of the index (or key in an associative array) in this way:

How to Use a for Loop in PHP

The for loop is similar to while, but instead of defining the variable used in the conditional before the loop, and instead of incrementing the index variable manually, it’s all done in the first line:

You can use the for loop to iterate over an array in this way:

How to Use the break and continue Statements in PHP

In many cases you want the ability to stop a loop on demand.

For example you want to stop a for loop when the value of the variable in the array is 'b' :

This makes the loop completely stop at that point, and the program execution continues at the next instruction after the loop.

If you just want to skip the current loop iteration and keep looking, use continue instead:

Functions are one of the most important concepts in programming.

You can use functions to group together multiple instructions or multiple lines of code, and give them a name.

For example you can make a function that sends an email. Let’s call it sendEmail , and we'll define it like this:

And you can call it anywhere else by using this syntax:

You can also pass arguments to a function. For example when you send an email, you want to send it to someone – so you add the email as the first argument:

Inside the function definition we get this parameter in this way (we call them parameters inside the function definition, and arguments when we call the function):

You can send multiple arguments by separating them with commas:

And we can get those parameters in the order they were defined:

We can optionally set the type of parameters:

Parameters can have a default value, so if they are omitted we can still have a value for them:

A function can return a value. Only one value can be returned from a function, not more than one. You do that using the return keyword. If omitted, the function returns null .

The returned value is super useful as it tells you the result of the work done in the function, and lets you use its result after calling it:

We can optionally set the return type of a function using this syntax:

When you define a variable inside a function, that variable is local to the function, which means it’s not visible from outside. When the function ends, it just stops existing:

Variables defined outside of the function are not accessible inside the function.

This enforces a good programming practice as we can be sure the function does not modify external variables and cause “side effects”.

Instead you return a value from the function, and the outside code that calls the function will take responsibility for updating the outside variable.

You can pass the value of a variable by passing it as an argument to the function:

But you can’t modify that value from within the function.

It’s passed by value , which means the function receives a copy of it, not the reference to the original variable.

That is still possible using this syntax (notice I used & in the parameter definition):

The functions we've defined so far are named functions .

They have a name.

We also have anonymous functions , which can be useful in a lot of cases.

They don’t have a name, per se, but they are assigned to a variable. To call them, you invoke the variable with parentheses at the end:

Note that you need a semicolon after the function definition, but then they work like named functions for return values and parameters.

Interestingly, they offer a way to access a variable defined outside the function through use() :

Another kind of function is an arrow function .

An arrow function is an anonymous function that’s just one expression (one line), and implicitly returns the value of that expression.

You define it in this way:

Here’s an example:

You can pass parameters to an arrow function:

Note that as the next example shows, arrow functions have automatic access to the variables of the enclosing scope, without the need of use() .

Arrow functions are super useful when you need to pass a callback function. We’ll see how to use them to perform some array operations later.

So we have in total 3 kinds of functions: named functions , anonymous functions , and arrow functions .

Each of them has its place, and you’ll learn how to use them properly over time, with practice.

Another important set of looping structures, often used in functional programming, is the set of array_map() / array_filter() / array_reduce() .

Those 3 built-in PHP functions take an array, and a callback function that in each iteration takes each item in the array.

array_map() returns a new array that contains the result of running the callback function on each item in the array:

array_filter() generates a new array by only getting the items whose callback function returns true :

array_reduce() is used to reduce an array to a single value.

For example we can use it to multiply all items in an array:

Notice the last parameter – it’s the initial value. If you omit that, the default value is 0 but that would not work for our multiplication example.

Note that in array_map() the order of the arguments is reversed. First you have the callback function and then the array. This is because we can pass multiple arrays using commas ( array_map(fn($value) => $value * 2, $numbers, $otherNumbers, $anotherArray); ). Ideally we’d like more consistency, but that’s what it is.

Let’s now jump head first into a big topic: object-oriented programming with PHP.

Object-oriented programming lets you create useful abstractions and make your code simpler to understand and manage.

How to Use Classes and Objects in PHP

To start with, you have classes and objects.

A class is a blueprint, or type, of object.

For example you have the class Dog , defined in this way:

Note that the class must be defined in uppercase.

Then you can create objects from this class – specific, individual dogs.

An object is assigned to a variable, and it’s instantiated using the new Classname() syntax:

You can create multiple objects from the same class, by assigning each object to a different variable:

How to Use Properties in PHP

Those objects will all share the same characteristics defined by the class. But once they are instantiated, they will have a life of their own.

For example, a Dog has a name, an age, and a fur color.

So we can define those as properties in the class:

They work like variables, but they are attached to the object, once it's instantiated from the class. The public keyword is the access modifier and sets the property to be publicly accessible.

You can assign values to those properties in this way:

Notice that the property is defined as public .

That is called an access modifier. You can use two other kinds of access modifiers: private and protected . Private makes the property inaccessible from outside the object. Only methods defined inside the object can access it.

We’ll see more about protected when we’ll talk about inheritance.

How to Use Methods in PHP

Did I say method? What is a method?

A method is a function defined inside the class, and it’s defined in this way:

Methods are very useful to attach a behavior to an object. In this case we can make a dog bark.

Notice that I use the public keyword. That’s to say that you can invoke a method from outside the class. Like for properties, you can mark methods as private too, or protected , to restrict their access.

You invoke a method on the object instance like this:

A method, just like a function, can define parameters and a return value, too.

Inside a method we can access the object’s properties using the special built-in $this variable, which, when referenced inside a method, points to the current object instance:

Notice I used $this->name to set and access the $name property, and not $this->$name .

How to Use the Constructor Method in PHP

A special kind of method named __construct() is called a constructor .

You use this method to initialize the properties of an object when you create it, as it’s automatically invoked when calling new Classname() .

This is such a common thing that PHP (starting in PHP 8) includes something called constructor promotion where it automatically does this thing:

By using the access modifier, the assignment from the parameter of the constructor to the local variable happens automatically:

Properties can be typed .

You can require the name to be a string using public string $name :

Now all works fine in this example, but try changing that to public int $name to require it to be an integer.

PHP will raise an error if you initialize $name with a string:

Interesting, right?

We can enforce properties to have a specific type between string , int , float , string , object , array , bool and others .

What is Inheritance in PHP?

The fun in object oriented programming starts when we allow classes to inherit properties and methods from other classes.

Suppose you have an Animal class:

Every animal has an age, and every animal can eat. So we add an age property and an eat() method:

A dog is an animal and has an age and can eat too, so the Dog class – instead of reimplementing the same things we have in Animal – can extend that class:

We can now instantiate a new object of class Dog and we have access to the properties and methods defined in Animal :

In this case we call Dog the child class and Animal the parent class .

Inside the child class we can use $this to reference any property or method defined in the parent, as if they were defined inside the child class.

It’s worth noting that while we can access the parent’s properties and methods from the child, we can’t do the reverse.

The parent class knows nothing about the child class.

protected Properties and Methods in PHP

Now that we've introduced inheritance, we can discuss protected . We already saw how we can use the public access modifier to set properties and methods callable from outside of a class, by the public.

private properties and methods can only be accessed from within the class.

protected properties and methods can be accessed from within the class and from child classes.

How to Override Methods in PHP

What happens if we have an eat() method in Animal and we want to customize it in Dog ? We can override that method.

Now any instance of Dog will use the Dog 's implementation of the eat() method.

Static Properties and Methods in PHP

We’ve seen how to define properties and methods that belong to the instance of a class , an object.

Sometimes it’s useful to assign those to the class itself.

When this happens we call them static , and to reference or call them we don’t need to create an object from the class.

Let’s start with static properties. We define them with the static keyword:

We reference them from inside the class using the keyword self , which points to the class:

and from outside the class using:

This is what happens for static methods:

From the outside of the class we can call them in this way:

From inside the class, we can reference them using the self keyword, which refers to the current class:

How to Compare Objects in PHP

When we talked about operators I mentioned we have the == operator to check if two values are equal and === to check if they are identical.

Mainly the difference is that == checks the object content, for example the '5' string is equal to the number 5 , but it’s not identical to it.

When we use those operators to compare objects, == will check if the two objects have the same class and have the same values assigned to them.

=== on the other hand will check if they also refer to the same instance (object).

How to Iterate over Object Properties in PHP

You can loop over all the public properties in an object using a foreach loop, like this:

How to Clone Objects in PHP

When you have an object, you can clone it using the clone keyword:

This performs a shallow clone , which means that references to other variables will be copied as references – there will not a “recursive cloning” of them.

To do a deep clone you will need to do some more work.

What are Magic Methods in PHP?

Magic methods are special methods that we define in classes to perform some behavior when something special happens.

For example when a property is set, or accessed, or when the object is cloned.

We’ve seen __construct() before.

That’s a magic method.

There are others. For example we can set a “cloned” boolean property to true when the object is cloned:

Other magic methods include __call() , __get() , __set() , __isset() , __toString() and others.

You can see the full list here

We’re now done talking about the object oriented features of PHP.

Let’s now explore some other interesting topics!

Inside a PHP file you can include other PHP files. We have the following methods, all used for this use case, but they're all slightly different: include , include_once , require , and require_once .

include loads the content of another PHP file, using a relative path.

require does the same, but if there’s any error doing so, the program halts. include will only generate a warning.

You can decide to use one or the other depending on your use case. If you want your program to exit if it can’t import the file, use require .

include_once and require_once do the same thing as their corresponding functions without _once , but they make sure the file is included/required only once during the execution of the program.

This is useful if, for example, you have multiple files loading some other file, and you typically want to avoid loading that more than once.

My rule of thumb is to never use include or require because you might load the same file twice. include_once and require_once help you avoid this problem.

Use include_once when you want to conditionally load a file, for example “load this file instead of that”. In all other cases, use require_once .

The above syntax includes the test.php file from the current folder, the file where this code is.

You can use relative paths:

to include a file in the parent folder or to go in a subfolder:

You can use absolute paths:

In modern PHP codebases that use a framework, files are generally loaded automatically so you’ll have less need to use the above functions.

Speaking of paths, PHP offers you several utilities to help you work with paths.

You can get the full path of the current file using:

  • __FILE__ , a magic constant
  • $_SERVER['SCRIPT_FILENAME'] (more on $_SERVER later!)

You can get the full path of the folder where the current file is using:

  • the getcwd() built-in function
  • __DIR__ , another magic constant
  • combine __FILE__ with dirname() to get the current folder full path: dirname(__FILE__)

Every programmer makes errors. We’re humans, after all.

We might forget a semicolon. Or use the wrong variable name. Or pass the wrong argument to a function.

In PHP we have:

The first two are minor errors, and they do not stop the program execution. PHP will print a message, and that’s it.

Errors terminate the execution of the program, and will print a message telling you why.

There are many different kinds of errors, like parse errors, runtime fatal errors, startup fatal errors, and more.

They’re all errors.

I said “PHP will print a message”, but.. where?

This depends on your configuration.

In development mode it’s common to log PHP errors directly into the Web page, but also in an error log.

You want to see those errors as early as possible, so you can fix them.

In production, on the other hand, you don’t want to show them in the Web page, but you still want to know about them.

So what do you do? You log them to the error log.

This is all decided in the PHP configuration.

We haven’t talked about this yet, but there’s a file in your server configuration that decides a lot of things about how PHP runs.

It’s called php.ini .

The exact location of this file depends on your setup.

To find out where is yours, the easiest way is to add this to a PHP file and run it in your browser:

You will then see the location under “Loaded Configuration File”:

Screen Shot 2022-06-27 at 13.42.41.jpg

In my case it’s /Applications/MAMP/bin/php/php8.1.0/conf/php.ini .

Note that the information generated by phpinfo() contains a lot of other useful information. Remember that.

Using MAMP you can open the MAMP application folder and open bin/php . Go in your specific PHP version (8.1.0 in my case) then go in conf . In there you’ll find the php.ini file:

Screen Shot 2022-06-27 at 12.11.28.jpg

Open that file in an editor.

It contains a really long list of settings, with a great inline documentation for each one.

We’re particularly interested in display_errors :

Screen Shot 2022-06-27 at 12.13.16.jpg

In production you want its value to be Off , as the docs above it say.

The errors will not show up anymore in the website, but you will see them in the php_error.log file in the logs folder of MAMP in this case:

Screen Shot 2022-06-27 at 12.16.01.jpg

This file will be in a different folder depending on your setup.

You set this location in your php.ini :

Screen Shot 2022-06-27 at 12.17.12.jpg

The error log will contain all the error messages your application generates:

Screen Shot 2022-06-27 at 12.17.55.jpg

You can add information to the error log by using the error_log() function:

It’s common to use a logger service for errors, like Monolog .

Sometimes errors are unavoidable. Like if something completely unpredictable happens.

But many times, we can think ahead, and write code that can intercept an error, and do something sensible when this happens. Like showing a useful error message to the user, or trying a workaround.

We do so using exceptions .

Exceptions are used to make us, developers, aware of a problem.

We wrap some code that can potentially raise an exception into a try block, and we have a catch block right after that. That catch block will be executed if there’s an exception in the try block:

Notice that we have an Exception object $e being passed to the catch block, and we can inspect that object to get more information about the exception, like this:

Let’s look at an example.

Let's say that by mistake I divide a number by zero:

This will trigger a fatal error and the program is halted on that line:

Screen Shot 2022-06-26 at 20.12.59.jpg

Wrapping the operation in a try block and printing the error message in the catch block, the program ends successfully, telling me the problem:

Screen Shot 2022-06-26 at 20.13.36.jpg

Of course this is a simple example but you can see the benefit: I can intercept the issue.

Each exception has a different class. For example we can catch this as DivisionByZeroError and this lets me filter the possible problems and handle them differently.

I can have a catch-all for any throwable error at the end, like this:

Screen Shot 2022-06-26 at 20.15.47.jpg

And I can also append a finally {} block at the end of this try/catch structure to execute some code after the code is either executed successfully without problems, or there was a catch :

Screen Shot 2022-06-26 at 20.17.33.jpg

You can use the built-in exceptions provided by PHP but you can also create your own exceptions.

Working with dates and times is very common in programming. Let’s see what PHP provides.

We can get the current timestamp (number of seconds since Jan 1 1970 00:00:00 GMT) using time() :

When you have a timestamp you can format that as a date using date() , in the format you prefer:

Y is the 4-digit representation of the year, m is the month number (with a leading zero) and d is the number of the day of the month, with a leading zero.

See the full list of characters you can use to format the date here .

We can convert any date into a timestamp using strtotime() , which takes a string with a textual representation of a date and converts it into the number of seconds since Jan 1 1970:’s pretty flexible.

For dates, it’s common to use libraries that offer a lot more functionality than what the language can. A good option is Carbon .

We can define constants in PHP using the define() built-in function:

And then we can use TEST as if it was a variable, but without the $ sign:

We use uppercase identifiers as a convention for constants.

Interestingly, inside classes we can define constant properties using the const keyword:

By default they are public but we can mark them as private or protected :

Enums allow you to group constants under a common “root”. For example you want to have a Status enum that has 3 states: EATING SLEEPING RUNNING , the 3 states of a dog’s day.

So you have:

Now we can reference those constants in this way:

Enums are objects, they can have methods and lots more features than we can get into here in this short introduction.

PHP is a server-side language and it is typically used in two ways.

One is within an HTML page, so PHP is used to “add” stuff to the HTML which is manually defined in the .php file. This is a perfectly fine way to use PHP.

Another way considers PHP more like the engine that is responsible for generating an “application”. You don't write the HTML in a .php file, but instead you use a templating language to generate the HTML, and everything is managed by what we call the framework .

This is what happens when you use a modern framework like Laravel.

I would consider the first way a bit “out of fashion” these days, and if you’re just starting out you should know about those two different styles of using PHP.

But also consider using a framework like “easy mode” because frameworks give you tools to handle routing, tools to access data from a database, and they make it easier to build a more secure application. And they make it all faster to develop.

That said, we’re not going to talk about using frameworks in this handbook. But I will talk about the basic, fundamental building blocks of PHP. They are essentials that any PHP developer must know.

Just know that “in the real world” you might use your favorite framework’s way of doing things rather than the lower level features offered by PHP.

This does not apply just to PHP of course – it’s an “issue” that happens with any programming language.

How to Handle HTTP Requests in PHP

Let’s start with handling HTTP requests.

PHP offers file-based routing by default. You create an index.php file and that responds on the / path.

We saw that when we made the Hello World example in the beginning.

Similarly, you can create a test.php file and automatically that will be the file that Apache serves on the /test route.

How to Use $_GET , $_POST and $_REQUEST in PHP

Files respond to all HTTP requests, including GET, POST and other verbs.

For any request you can access all the query string data using the $_GET object. It's called superglobal and is automatically available in all our PHP files.

This is of course most useful in GET requests, but also other requests can send data as a query string.

For POST, PUT and DELETE requests you’re more likely to need the data posted as URL-encoded data or using the FormData object, which PHP makes available to you using $_POST .

There is also $_REQUEST which contains all of $_GET and $_POST combined in a single variable.

How to Use the $_SERVER Object in PHP

We also have the superglobal variable $_SERVER , which you use to get a lot of useful information.

You saw how to use phpinfo() before. Let’s use it again to see what $_SERVER offers us.

In your index.php file in the root of MAMP run:

Then generate the page at localhost:8888 and search $_SERVER . You will see all the configuration stored and the values assigned:

Screen Shot 2022-06-27 at 13.46.50.jpg

Important ones you might use are:


How to Use Forms in PHP

Forms are the way the Web platform allows users to interact with a page and send data to the server.

Here is a simple form in HTML:

You can put this in your index.php file like it was called index.html .

A PHP file assumes you write HTML in it with some “PHP sprinkles” using <?php ?> so the Web Server can post that to the client. Sometimes the PHP part takes all of the page, and that’s when you generate all the HTML via PHP – it’s kind of the opposite of the approach we're taking here now.

So we have this index.php file that generates this form using plain HTML:

Screen Shot 2022-06-27 at 13.53.47.jpg

Pressing the Submit button will make a GET request to the same URL sending the data via query string. Notice that the URL changed to localhost:8888/?name=test .

Screen Shot 2022-06-27 at 13.56.46.jpg

We can add some code to check if that parameter is set using the isset() function:

Screen Shot 2022-06-27 at 13.56.35.jpg

See? We can get the information from the GET request query string through $_GET .

What you usually do with forms, though is you perform a POST request:

See, now we got the same information but the URL didn’t change. The form information was not appended to the URL.

Screen Shot 2022-06-27 at 13.59.54.jpg

This is because we’re using a POST request , which sends the data to the server in a different way, through URL-encoded data.

As mentioned above, PHP will still serve the index.php file as we’re still sending data to the same URL the form is on.

We’re mixing a bunch of code and we could separate the form request handler from the code that generates the form.

So we can have this in index.php :

and we can create a new post.php file with:

PHP will display this content now after we submit the form, because we set the action HTML attribute on the form.

This example is very simple, but the post.php file is where we could, for example, save the data to the database, or to a file.

How to Use HTTP Headers in PHP

PHP lets us set the HTTP headers of a response through the header() function.

HTTP Headers are a way to send information back to the browser.

We can say the page generates a 500 Internal Server Error:

Now you should see the status if you access the page with the Browser Developer Tools open:

Screen Shot 2022-06-27 at 14.10.29.jpg

We can set the content/type of a response:

We can force a 301 redirect:

We can use headers to say to the browser “cache this page”, “don’t cache this page”, and a lot more.

How to Use Cookies in PHP

Cookies are a browser feature.

When we send a response to the browser, we can set a cookie which will be stored by the browser, client-side.

Then, every request the browser makes will include the cookie back to us.

We can do many things with cookies. They are mostly used to create a personalized experience without you having to login to a service.

It’s important to note that cookies are domain-specific, so we can only read cookies we set on the current domain of our application, not other application’s cookies.

But JavaScript can read cookies (unless they are HttpOnly cookies but we’re starting to go into a rabbit hole) so cookies should not store any sensitive information.

We can use PHP to read the value of a cookie referencing the $_COOKIE superglobal:

The setcookie() function allows you to set a cookie:

We can add a third parameter to say when the cookie will expire. If omitted, the cookie expires at the end of the session/when the browser is closed.

Use this code to make the cookie expire in 7 days:

We can only store a limited amount of data in a cookie, and users can clear the cookies client-side when they clear the browser data.

Also, they are specific to the browser / device, so we can set a cookie in the user’s browser, but if they change browser or device, the cookie will not be available.

Let’s do a simple example with the form we used before. We’re going to store the name entered as a cookie:

I added some conditionals to handle the case where the cookie was already set, and to display the name right after the form is submitted, when the cookie is not set yet (it will only be set for the next HTTP request).

If you open the Browser Developer Tools you should see the cookie in the Storage tab.

From there you can inspect its value, and delete it if you want.

Screen Shot 2022-06-27 at 14.46.09.jpg

How to Use Cookie-based Sessions in PHP

One very interesting use case for cookies is cookie-based sessions.

PHP offers us a very easy way to create a cookie-based session using session_start() .

Try adding this:

in a PHP file, and load it in the browser.

You will see a new cookie named by default PHPSESSID with a value assigned.

That’s the session ID. This will be sent for every new request and PHP will use that to identify the session.

Screen Shot 2022-06-27 at 14.51.53.jpg

Similarly to how we used cookies, we can now use $_SESSION to store the information sent by the user – but this time it’s not stored client-side.

Only the session ID is.

The data is stored server-side by PHP.

Screen Shot 2022-06-27 at 14.53.24.jpg

This works for simple use cases, but of course for intensive data you will need a database.

To clear the session data you can call session_unset() .

To clear the session cookie use:

How to Work with Files and Folders in PHP

PHP is a server-side language, and one of the handy things it provides is access to the filesystem.

You can check if a file exists using file_exists() :

Get the size of a file using filesize() :

You can open a file using fopen() . Here we open the test.txt file in read-only mode and we get what we call a file descriptor in $file :

We can terminate the file access by calling fclose($fd) .

Read the content of a file into a variable like this:

feof() checks that we haven’t reached the end of the file as fgets reads 5000 bytes at a time.

You can also read a file line by line using fgets() :

To write to a file you must first open it in write mode , then use fwrite() :

We can delete a file using unlink() :

Those are the basics, but of course there are more functions to work with files .

PHP and Databases

PHP offers various built-in libraries to work with databases, for example:

  • MySQL / MariaDB

I won't cover this in the handbook because I think this is a big topic and one that would also require you to learn SQL.

I am also tempted to say that if you need a database you should use a framework or ORM that would save you security issues with SQL injection. Laravel’s Eloquent is a great example.

How to Work with JSON in PHP

JSON is a portable data format we use to represent data and send data from client to server.

Here’s an example of a JSON representation of an object that contains a string and a number:

PHP offers us two utility functions to work with JSON:

  • json_encode() to encode a variable into JSON
  • json_decode() to decode a JSON string into a data type (object, array…)

How to Send Emails with PHP

One of the things that I like about PHP is the conveniences, like sending an email.

Send an email using mail() :

To send emails at scale we can’t rely on this solution, as these emails tend to reach the spam folder more often than not. But for quick testing this is just helpful.

Libraries like will be super helpful for more solid needs, using an SMTP server.

Composer is the package manager of PHP.

It allows you to easily install packages into your projects.

Install it on your machine ( Linux/Mac or Windows ) and once you’re done you should have a composer command available on your terminal.

Screen Shot 2022-06-27 at 16.25.43.jpg

Now inside your project you can run composer require <lib> and it will be installed locally. For example let's install the Carbon library that helps us work with dates in PHP

It will do some work:

Screen Shot 2022-06-27 at 16.27.11.jpg

Once it’s done, you will find some new things in the folder composer.json that lists the new configuration for the dependencies:

composer.lock is used to “lock” the versions of the package in time, so the exact same installation you have can be replicated on another server. The vendor folder contains the library just installed and its dependencies.

Now in the index.php file we can add this code at the top:

and then we can use the library!

Screen Shot 2022-06-27 at 16.34.47.jpg

See? We didn’t have to manually download a package from the internet and install it was all fast, quick, and well organized.

The require 'vendor/autoload.php'; line is what enables autoloading . Remember when we talked about require_once() and include_once() ? This solves all of that – we don’t need to manually search for the file to include, we just use the use keyword to import the library into our code.

When you’ve got an application ready, it’s time to deploy it and make it accessible from anyone on the Web.

PHP is the programming language with the best deployment story across the Web.

Trust me, every single other programming language and ecosystem wishes they were as easy as PHP.

The great thing about PHP, the thing it got right and allowed it to have the incredible success it has had, is the instant deploy.

You put a PHP file on a folder served by a Web server, and voilà – it just works.

No need to restart the server, run an executable, nothing.

This is still something that a lot of people do. You get a shared hosting for $3/month, upload your files via FTP, and you're done.

These days, though, I think Git deploy is something that should be baked into every project, and shared hosting should be a thing of the past.

One solution is always having your own private VPS (Virtual Private Server), which you can get from services like DigitalOcean or Linode.

But managing your own VPS is no joke. It requires serious knowledge and time investment, and constant maintenance.

You can also use the so-called PaaS (Platform as a Service), which are platforms that focus on taking care of all the boring stuff (managing servers) and you just upload your app and it runs.

Solutions like DigitalOcean App Platform (which is different from a DigitalOcean VPS), Heroku, and many others are great for your first tests.

These services allow you to connect your GitHub account and deploy any time you push a new change to your Git repository.

You can learn how to setup Git and GitHub from zero here .

This is a much better workflow compared to FTP uploads.

Let’s do a bare bones example.

I created a simple PHP application with just an index.php file:

I add the parent folder to my GitHub Desktop app, I initialize a Git repo, and I push it to GitHub:

Screen Shot 2022-06-27 at 17.26.24.jpg

Now go on .

If you don’t have an account yet, use my referral code to sign up get $100 free credits over the next 60 days and you can work on your PHP app for free.

I connect to my DigitalOcean account and I go to Apps → Create App.

I connect my GitHub Account and select the repo of my app.

Make sure “Autodeploy” is checked, so the app will automatically redeploy on changes:

Screen Shot 2022-06-27 at 17.31.54.jpg

Click “Next” then Edit Plan:

Screen Shot 2022-06-27 at 17.32.24.jpg

By default the Pro plan is selected.

Use Basic and pick the $5/month plan.

Note that you pay $5 per month, but billing is per hour – so you can stop the app any time you want.

Screen Shot 2022-06-27 at 17.32.28.jpg

Then go back and press “Next” until the “Create Resources” button appears to create the app. You don’t need any database, otherwise that would be another $7/month on top.

Screen Shot 2022-06-27 at 17.33.46.jpg

Now wait until the deployment is ready:

Screen Shot 2022-06-27 at 17.35.00.jpg

The app is now up and running!

Screen Shot 2022-06-27 at 17.35.31.jpg

You’ve reached the end of the PHP Handbook!

Thank you for reading through this introduction to the wonderful world of PHP development. I hope it will help you get your web development job, become better at your craft, and empower you to work on your next big idea.

Note: you can get a PDF, ePub, or Mobi version of this handbook for easier reference, or for reading on your Kindle or tablet.

Read more posts .

If this article was helpful, share it .

Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. Get started

  • Enterprise Java
  • Web-based Java
  • Data & Java
  • Project Management
  • Visual Basic
  • Ruby / Rails
  • Java Mobile
  • Architecture & Design
  • Open Source
  • Web Services content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More .

It’s no secret; writing code documentation ranks right up there with attending meetings and the using the telephone as among the least favorite aspects of any developer’s job. This shouldn’t really come as a surprise though, since not only is writing documentation a pretty unexciting task, but it can be difficult to maintain over the lifetime of a project given changing features and code refactoring. Nonetheless, it’s a crucial task if you and your team intend to create code that is maintainable well into the future, stretching even beyond your own role with the project ends.

To alleviate some of the tedium and potential for incorrectness, automated documentation tools were created. These tools parse comments and code declarations found in project source files, producing organized documentation in a user-friendly format. Some examples of such tools include POD for Perl, JavaDoc for Java , and Pydoc for Python. These tools are extremely popular among users of these respective languages due to the increased productivity they can bring to large and small projects alike.

Yet many PHP developers aren’t aware that a similar tool is available for PHP. PHPDocumentor ( ) is a powerful utility capable of generating documentation from source code comments. Capable of producing documentation in Docbook, HTML, PDF, and Windows Compiled HTML Help formats, PHPDocumentor can go a long way towards taking away the hassle of creating and maintaining end user documentation in a variety of formats. In this article, I’ll introduce this great tool, showing you how to structure your code comments in a manner supported by PHPDocumentor, and generate resulting documentation in a format convenient to you.

A Simple Example

PHPDocumentor builds documentation by parsing a comment known as a DocBlock . A DocBlock is a C++-style PHP comment that looks like this:

To document a function, you would place a DocBlock directly before the function declaration, like so:

This particular DocBlock consists of two items, namely a short and long description. PHPDocumentor knows to separate the two by ending the short description with either a blank line or a concluding period. While the short description is constrained to a maximum three lines, the long description can be as long as is required.

Of course, functions aren’t the only language element documentable by PHPDocumentor. You can also document classes, class variables, class methods, define statements, global variables, include/include_once/require/require_once statements, and procedural pages. Let’s consider a slightly longer example that demonstrates documentation of several different language elements:

Generating the documentation produces the output shown in Figure 1.

In the previous section I introduced you two DocBlock components: the short and long description. There’s yet another item that you might wish into a DocBlock, known as a tag . Tags are predefined keywords prefixed with an @ symbol, and they help you create more formal documentation by defining key items of information such as the author, version number, return value, todo items, and copyright. Returning to the circle() function, I’ll modify the DocBlock, adding a few tags:

/** * Calculate circumference of circle * * The function circle() calculates the circumference of a circle, * accepting its radius as input and returning the circumference * * @author Jason Gilmore * @param float $radius Radius of the circle * @version 3.2 */

Regenerating the documentation produces the output shown in Figure 2.

You can view a complete list of supported tags by navigating to the PHPDoc Documentation .

Thus far I’ve based the examples from a single file. While suffice for helping you get acquainted with PHPDocumentor, even simple applications often consist of several files. PHPDocumentor is capable of creating documentation for multiple file projects, done by dividing files and classes into packages . Specifically, constants, functions, and global variables are packaged using a page-level DocBlock, while class variables and methods are packaged using a class-level DocBock. I’ll show you how to use packages in the former manner. Let’s add a second file to the application, titled square.php :

<?php /** * This file contains the square() function. * @package squarePackage */ /** * Include the Web page template header */ INCLUDE ""; /** * Calculate area of a square * * The function square() calculates the area of a square, * accepting the length of each side as input and returning the area * */ function square($length) { $area = $length * $length; return $area; }?>

Note that the page-level DocBlock is placed at the very beginning of the file, and the first item-level DocBlock directly follows it. Also note the reference to @package named squarePackage . Next I’ll modify the circle.php file, adding the following page-level DocBlock to the top:

/** * This is some file * @package circlePackage */

Regenerating the documentation produces a table of contents consisting of links to the circlePackage and squarePackage . Clicking on each link will take you to a document similar to that found in Figure 2.

Building the Documentation

You can build the project documentation using the command-line script phpdoc, or a Web-based interface. I’ll show you how to use the latter. To begin, download the latest version of PHPDocumentor from the website , extracting it to a protected area of your web document root. I’m presently using version 1.3.0 RC3, which is the first version to be PHP 5 compatible. Then navigate to the index.html file located in the PhpDocumentor directory. You’ll see several tabs at the top of the interface, including Introduction , Config , Files , Output , Options , Credit , and Links . Feel free to browse each tab to get an idea of their purpose, however for the purposes of this example you’ll need to be concerned with only the Files and Output tabs. Navigate to the Files tab, depicted in Figure 3.

Note that you can specify input files in four manner: by file, by directory, files to ignore, and by package. I’ve added the directory containing the circle.php and square.php files. Next click on the Output tab, depicted in Figure 4.

The Target field is used to specify the documentation destination directory. The Output type dropdown lists the variety of templates and documentation types available to you. Throughout this tutorial I’ve used HTML:Smarty:default . Feel free to experiment with other formats. Add a target directory and press the create button located to the lower-right of the window. You can scroll through the output appearing in the lower frame to review PHPDocumentor’s actions. Assuming all goes okay, the output will conclude with “Operation Completed!!”. Review your documentation by navigating to the target folder.

In this article I’ve introduced only a smattering of PHPDocumentor’s capabilities, although hopefully this brief article made it apparent that this is one tool you simply can’t live without. As always, I welcome questions and comments. Please e-mail me at wj AT!

About the Author

W. Jason Gilmore ( ) is the Open Source Editorial Director for Apress ( ). He’s the author of Beginning PHP 5 and MySQL: Novice to Professional (Apress, 2004. 748pp.). His work has been featured within many of the computing industry’s leading publications, including Linux Magazine, O’Reillynet, Devshed,, and Webreview. Jason is also the author of A Programmer’s Introduction to PHP 4.0 (453pp., Apress). Along with colleague Jon Shoberg, he’s co-author of “Out in the Open,” a monthly column published within Linux magazine.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

What is the role of a project manager in software development, how to use optional in java, overview of the jad methodology, microsoft project tips and tricks, how to become a project manager in 2023, related stories, how to use azure devops’ work items and php, working with php, git, and azure devops, using php for system administration.

August 11, 2015 Code Commenting And PHP Documentation Generation Written by Artem

Code commenting and PHP documentation generation

Why do we need comments in code? How to write them? Where they are necessary and where they are not? How to comment code correctly? How to create the same documentation style for all members of the team? What are the tools for documentation generation? I will try to answer all the questions and share with you my ideas about this question.

So, there are two types of program documentation. The first type is to write comment in the code itself. The second variant is when the third party tool or repository is used, for example WIKI-engine, where the principles of application operation, the usage examples, the interaction modules are described, it is also provided with flowcharts and diagrams, generally speaking everything that you can’t write in code.

Documentation Location Variants

Let’s start with documentation within the program code. Though, this is not the aim of this article. In the open source projects , we often can notice that the documentation articles are kept in the same repository as the base code. For example, in the PHP fake fixtures library the documentation is in the README file, and if you want to read it to the end, you’ll have to scroll a little bit.In Guzzle, popular HTTP client for PHP, usage instructions are kept in a separate docs folder. Keeping documentation close to code is good and very handy. Downloading a vendors package once, you have code and documentation. If your library is not big, if it is stable and doesn’t involve frequent API changes in the future which result in permanent documentation rewriting, you can safely place the documentation in the repository of your project.

But everything has its reasonable limits. For example, if you are planning to create your own framework which is written by the team of developers and plan permanent releases, the framework has to be fully documented and what is more, the documentation must be translated into several languages. In this case putting documentation into repository of the project is not quite correct. Because constant corrections, updates, translations and debuggings would be quite typical. They will cause a large number of commits — fixes that spoil the history of the project. Navigating commit history when code changes are lost documentation changes is complex and uncomfortable.

In this case it is better to create a standalone repository for documentation, for example, as it was made for Symfony . GitHub, GitLab, Bitbucket also provide built-in WIKI tool that is attached to the project and is not a standalone repository. But you can also access it via Git which means you can copy all documentation, edit it in the editor you personally prefer, group modifications into commits, send them to server and get new comments.

Here’s an example of a well-organized WIKI for D3.js visualization library. Of course, it is possible to create a web site for a product and to put its documentation there. But if you use one of the methods described above, then you will be able to generate documentation web pages from your Git or WIKI repository — there’re tools for it. If you prefer overall solutions, you should pay attention to Confluence by Atlassian. It has much more features than WIKI-engine.

Commenting Code Inside The Code

Now let’s get back to documenting code in the code itself. I am writing this article based on my own experience but recently I’ve read “Clean Code” by Robert Martin so I’m going to cite this book when it’s relevant. The first message from Robert Martin is that the comment is the sign of failure. Comments are written only to indicate the wrong of a programmer , who couldn’t clearly express his idea through the programming language. The process of code analysis is a very broad concept and it goes far beyond this article. But let me share with you a trick for writing a really good code: you should write it so that it could be read as if it was sentences. The object-oriented programming is much more easier than functional, a widespread practice of naming classes with nouns and methods with verbs makes code look more natural. For example, we have a rabbit and let’s describe some of its basic functions as if they were an interface:

We simply create one object from Rabbit class:

Code is easily readable. Method run makes rabbit run, method stop is an intuitive command, it stops the previous action and rabbit stops. Now let’s teach our rabbit some tricks and make him run a fixed distance, which we will pass as parameter to the method run .

And he ran... But we can’t get what 100 means. Does this number mean minutes, meters, or foots? It could be fixed by means of commentary:

If a rabbit starts to “run” in several places and strings of your code, each of them needs additional commentaries. Commentaries will be duplicated and should be maintained in several places at once. The first thing you can do to avoid commentaries — is to replace number by variable.

In this case you don’t need a comment, because the code readability becomes a little bit better and you can see that the rabbit runs for 100 meters in the code. But the best variant will be to add context to the method name.

Rabbit is a noun, run is an adverb, in metres is a context, which we add to the method so that it captures the essence. It is possible to write methods using this scheme.

They will capture the essence of the method without additional comments. Just give your variables and methods correct names and you will reduce the amount of unnecessary commentaries in your code. Robert Martin gives a good advice on this point:

Don’t spend your time writing comments, which explain the mess you created, — spend it to fix it.

What if the comment is too long? How to turn it into the method name? You shouldn’t be afraid of long method names. Method length should be appropriate to capture the essence and don’t turn the method into an unreadable text. These methods are OK in this regard:

This is too much:

This method is hard to read, the architecture is incorrect. It can be refactored, for example, like this:

There are also exceptions in the length of method names. For example, when you write specifications for phpSpec , you may have no limits in the method length, the main thing is for your code to capture the essence. Here’s a code example from phpSpec documentation:

In specifications underscore is used in methods names and it’s easier to read long sentences this way. It doesn’t correspond to the PSR standard where camelCase is used, but it will be ok for readability of the tests.

The sense of appropriate length of the methods will come with time and experience. You may also look at examples from popular frameworks and libraries.

Comments Characteristics


Very often programmers change code, but forget to change comments. Especially when several programmers work on the same section. There are comments but they are written by one of the programmers and others don’t dare to change comments written by another programmer or too lazy to do this, or just don’t pay attention. As a result, these old out-of-date comments will only confuse the newcomer. The solution of this problem is quite simple. Alternatively, always pay attention to the up-to-dateness of commentaries but it will require your attention and effort. Or simply delete old comments. No comments is better than old outdated comments.

It means that comment is needless and is written in place where everything is clear without a commentary. Here’s an example of code with extra comments:

If we remove comments, code will remain clean:


While writing a program, you can quickly write down your idea by placing comment in the code. When later you get back to that piece, the comment will remind you about your thought and you will be able to continue. After your idea was turned into code, you should remove the incomplete commentary or complete it. In other words, don’t make readers wonder what did you mean. As an example let’s start describe how rabbit eats:

What does “the rabbit will die” comment mean? It is clear when it happens in the real life. And what about the program? What did the author wanted to do after this? To release the memory taken by rabbit? To mention an exception and then finish it in another piece of code? In this code with rabbit nothing happens, the rabbit simply doesn’t get new calories when eating anything other than carrot and cabbage. But for a newcomer, who will be finishing the code, the author’s idea will remain unclear. It is likely, that a newcomer will delete the commentary and make it in his own way.


All men are liable to make mistakes. But programmers make them not only in code, but also in the comment blocks. Because of inattention, tiredness or lack of foreign language skills, comments are in a mess and confuse others. Unfortunately, it happens. The only advice I can give you is to be responsible for your comments. If you decided to write something, you should write it correctly. You should be a perfectionist while writing comments.


When unknown or non-obvious terms are used in a certain piece of code.

Here we can see that the growth of the rabbit is determined by some index, which depends on some factors. In this piece of code it is unclear what rabbit growth index is and how we can calculate it. It’s better to remove this comment and place a more detailed one after function.

So, We Shouldn’t Write The Comments At All, Right?

We should write them, but we have to take responsibility for them. There are crucial moments when they are necessary.

Informational Value

In some places comments are required. When it is necessary to explain the algorithm or when a group of programmers had to use “hacks” in the code and to leave a comment about it. To describe the reason why it was made, what the commentary is about and when it has to be corrected. But you should try to choose correct names for your variables and methods.

Regular expressions make me numb and I have to spend lots of time to understand them. In this case the informational won’t be excessive.

There many ways to solve the same task in programming . Each programmer has his own programming style, that’s why it can be difficult for him to scan through code written by somebody else. If you prefer a certain programming style or if you know from practice that algorithms you use are difficult to read, put some help text before the complex piece of code.

Notifications and warnings

There are some cases when you can’t use certain function, for example:

  • the necessary extension wasn’t installed in production or the vendor wasn’t updated;
  • it takes too long to execute one of the functions and it is better not to launch it;
  • because of the high resource requirements you can’t perform the cycle more than a certain number of times.

If you face such situation, comments will be very useful.

When a certain line of code is so important that you have to pay extra attention to it. I faced a problem once when multibyte functions encoding wasn’t set on staging and spent lots of time on searching and solving this issue. When the problem was solved, I added to my code a parameter manual with a commentary explaining why I did it:

One more advice from Dean Martin:

Don’t comment a bad code — rewrite it.

When you come across an unclear code and spent a lot of time trying to understand it, and then leave several comments for the next developer, you should understand that the code won’t become better. In this situation, if you understand the code, try refactoring it to make it more readable. The motto of the boy scout is “Leave the campground (code) cleaner than the way you found it”.

Making Documentation With The Help Of Doc.blocks

There is a separate kind of PHP comments that has its own standard — it is called DocBlock). There is a tool phpDocumentor (also known as phpDoc) for processing docblocks. It can read docblocks from code and create documentation based on them. DocBlock is a combination of DocComment and descriptions placed in it based on PHPDoc standard. There is a support of C-type multiple line comments (DocComment):

DocBlock is distinguished by the additional “star” sign /** in the beginning of the comment.

It is possible for DocBlock to have only one line but it must begin with /** nonetheless.

PHP Doc standard for DOCUMENTING PHP CODE is based on javaDoc for Java. An important component of Docbloc are tags and annotations which make comments semantic. Tag or annotations begin with @ , for example.

In the example above @param , @return and @throws are PHPDoc tags and they will be parsed using phpDocrumentor. @Rest\Post("/login") is an annotation to FOSRestBundle . The difference between annotations and tags is that tags only document PHP code and annotations add or change code. The distinctive feature of PHP annotations comparing with Java ones is that Java annotations are part of Java while PHP annotations are commentaries and to use them you should use reflection . Maybe in the future annotations will become part of PHP but currently to read them you should use this parser . It’s also worth noticing that if we change the beginning of dockblock from /** to /* this won’t be a dockblock, even if it contains tags or annotations, and the parser will ignore it.

Dockblocks are so widely used in the community of PHP programmers, that PSR-5 (PHP Standard Recommendation) is prepared on the dockblock basis. When I have been writing this article it was a draft copy.

In PHP using dockblocks you can document the following elements:

  • interfaces;
  • class constants;
  • properties;

It is also important that each dockblock can only be applied to one structure element. It means that each function, variable and class has its own dockblock.

There are many tags in PHPDoc but not all tags can be applied to all structure elements. Below there is a list of tags, which are already exist and their use and explanation.

  • @api (method) defines the stable public methods, which won’t change their semantics up to the next major release.
  • @author (in any place) defines the name or an email of the author who wrote the following code.
  • @copyright (in any place) is used to put your copyright in the code.
  • @deprecated (in any place) is a useful tag which means that this element will disappear in the next versions. Usually there is a comment with the code you should use instead. Also, most of the IDE highlight places where old methods are used. When it is necessary to clean the out-of-date code for the new release, it will be easy to search by this tag.
  • @example (in any place) is used for inserting a link to a file or a web page where the example of code usage is shown. Currently phpDocumentor claims that this tag is not fully supported.
  • @filesource (file) is a tag which you can place only at the very beginning of the php file because you can apply this tag only to a file and to include all code to the generated documentation.
  • @global (variable) — at this moment this tag is not supported, may be it will be implemented in the next versions when it is updated and reworked.
  • @ignore (any place) — a dockblock with this tag won’t be processed when generating documentation, even if there are other tags.
  • @internal (any place) — often used with tag @api, to show that the code is used by inner logic of this part of the program. Element with this tag won’t be included in the documentation.
  • @license (file, class) shows the type of license of the written code.
  • @link (any place) is used for adding links but according to the documentation this tag is not fully supported.
  • @method (class) is applied to the class and describes methods processed with function __call() .
  • @package (file, class) divides code into logical subgroups. When you place classes in the same namespace, you indicate their functional similarity. If classes belong to different namespaces but have the same logical characteristic, they can be grouped using this tag (for example this is the case with classes that all work with customer’s cart but belong to different namespaces). But it is better to avoid such situation. For example, Symfony code style doesn’t use this tag.
  • @param (method, function) describes the incoming function parameters. It’s worth noticing that if you describe the incoming parameters for a certain function using dockblocks, you have to describe all parameters, not only one or two.
  • @property (class) — as well as @method this tag is placed in the dockblock of the class, but its function is to describe the properties accessed with the help of magic functions __get() and __set() .
  • @property-read, @property-write (class) are similar to the previous tag but they process only one magic method __get() or __set() .
  • @return (method, function) is used for describing value returned by the function. You can specify its type and PhpStorm will pick it and give you different tips, but let’s talk about this later.
  • @see (any place) — using this tag you can insert links on external resources (just like with @link ), but it also allows to put relative links to classes and methods..
  • @since (any place) — you can indicate the version in which the piece of code appeared.
  • @source (any place, except the beginning) — with the help of this tag you can place pieces of the source code in the documentation (you set the beginning and the end code line)
  • @throws (method function) is used for specifying exceptions which can be called out by this function.
  • @todo (any place) — the most optimistic tag used by programmers as a reminder of what need to be done in a certain piece of code. IDE have an ability to detect this tag and group all parts of the code in a separate window which is very convenient for further search. This is the working standard and is used very often.
  • @uses (any place) is used for displaying the connection between different sections of code. It is similar to @see . The difference is that @see creates unidirectional link and after you go to a new documentation page you won’t have a backward link while @uses gives you a backward navigation link.
  • @var (variable) is used to specify and to describe variables similar to those used inside the functions and for the class properties. You should distinguish this tag and @param . Tag @param is used only in dockblocks for functions and describes the incoming parameters and @var is used to describe variables.
  • @version (any place) denotes the current program version in which this class, method, etc. appeares.

Outdated tags, which most likely won’t be supported in the future:

  • @category (file, class) was used to group packages together.
  • @subpackage (file, class) was used to mark the specific groups in the package.

Not all tags are equally popular. @var, @param, @return, @todo, @throws are most widely used. The others are less popular. And I have never met such tags as @property and @method , because it is dangerous to work with magic!

Ease To Use Dockblocks In IDE

If you are developing an open source project it is of course necessary to document public API using dockblocks. It not only gives you the ability to generate the final documentation but also allows other programmers to comfortably use your code in their IDE. As for your private code for the outsource project, dockblocks usage might seem a little bit irrelevant, but anyway I advise you to use them, because they will speed up your development.

Let’s take the most popular PHP IDE for PHP — PhpStorm . And look at the previous example of rabbit search:

What do variables $rabbits and $rabbit mean? PhpStorm knows nothing about this. PHP is weakly typed and the type of function result is not strictly specified in the description (hi there, PHP 7 where it will be implemented). That’s why you should tell your IDE how to deal with certain parts of code using dockblocks. There are several variants. You can do like this:

Or add tag @return in the method findRabbitsInLocations :

Please pay attention that we specify Rabbit[] and not Rabbit . Brackets make it clear that the array of class objects is returned. If we remove the brackets it means that the method returns one example of the class Rabbit. You can also write it like this @return null|Rabbit[] , the vertical stick means OR, in this case we point out that the method will return the array of rabbits or null .

No matter which way of pointing out the type you chose, now PHPStorm will show you some hints and tips after you type $rabbit-> and wait for a moment.

Code commenting and PHP documentation generation

This happens because PHPStorm knows that in the $rabbits variable is returned by Rabbit objects array. Next in foreach cycle $rabbit variable gets one element of the array which is an example of the Rabbit class and PHPStorm shows you all available public methods from this class. This way you can use classes with public methods written by your colleagues without taking your hands off the keyboard.

PHPStorm will provide you with hints and if the method has a clear name, you will be able to use it even without reading the source code and documentation.

One more useful feature available to you when using dockblocks with PHPStorm are warnings about wrong access parameters. Let’s finish writing the dockblock for one of the methods of Rabbit class:

Here we indicate that we have to use an integer for access (in PHP 7 it will be possible to set the number by means of syntax). What will happen if we pass an array in this method?

Code commenting and PHP documentation generation

PHPStorm highlights it and gives a hint that int is excepted here while you are using array . Very convenient, isn’t it? Hints will also be shown for mismatched classes and interfaces. If your method supports several types of incoming arguments, divide them using |. In this example if the method runInMetres() can work with arrays, you may write @param int|array $metres Metres and dockblock will stop showing warnings.

PhpStorm can also can generates dockblocks. Place the cursor on the line above the function, class or variable declaration, type /** and push Enter . IDE will generate a dockblock template you can change a little if you want. You can also run dockblock generation using Alt + Insert .

How Follow Commenting Styles

It’s good if all members of the team follow the rules of commenting PHPDoc. But in practice it’s rarely a case. Only perfectionists adhere to the standard, and also those who have been using dockblocks for a long time and it has become a habit for them. Some beginner programmers want to use dockblocks but sometimes forget to use them or don’t fully understand tags. Of course, there are tough nuts who don’t use dockblocks even if the team uses them.

To reduce the discomfort, you each member of the team should turn on dockblock inspection in the PhpStorm: Settings > Editor > Inspections > PHPDoc and mark all the checkboxes:

Code commenting and PHP documentation generation

Of course, you can’t force everyone to follow the rules. For the laziest people I’d like to provide an advice from “Clean Code” once again (it’s about code formatting, but implications are the same):

The rules must be respected by all members of the group. This means that each member of the group should be reasonable enough to know that no matter how the braces are placed, unless everyone agreed to place them in the same way.

Generating Documentation With PhpDocumentor

Now when everybody follows the rules and your code is full of dockblocks, you can generate the documentation. I write much about phpDocumentor documentation, only show you the most necessary commands, the other best practices on documenting php code you can find at the official website .

So you have to install phpDocumentor. It can be installed globally this way:

Or add it as a requirement to composer.json of your project.

And now when you are in the directory of the project which is full of dockblocks, simply run it from console.

As I already mentioned this is the most necessary set of options for documentation generation, the option -d src/ shows the way to the files, which you want to work with. The generated information will be located in the folder called output . Of course, this utility has different specifications and lots of features. Here’s a PHPDocumentor example code and you can choose the template which already exists or create your own.

Generating Documentation With Sami

One more PHP documenting tool based on dockblocks is a utility called Sami. Maybe it’s not as popular but I decided to mention it because the Symfony documentation is generated using Sami. And Fabien Potencier who created this utility mentions it in his blog .

Sami documentation generator differs from phpDocumentor because its configuration is stored in PHP files. In general it has more customization potential than phpDocumentor but you will have to configure it all manually, write some code in other words. You can even redefine different pieces of code which are responsible for documentation generation. All the necessary templates can be found at TWIG plus they are easy to redefine. For more detailed information about Sami go to the GitHub page .

This is just a small review of the problem of documenting code in PHP and commenting it. Here you will find a little bit of everything to encourage the desire for digging deeper into this topic. If you are a PHP beginner, I advise you to read a detailed documentation about phpDocumentor . If you are an experienced developer, you can share some of your personal experince by writing a comment below. ^_^

How to Choose Technology Stack for Web Application Development: 10 Valuable Tips

  • web-development ,

phpDocumentor Guide to Creating Fantastic Documentation

What makes good documentation this is unanswerable, but there are a few things to keep in mind, why write good documentation for open source code.

Writing good documentation is essential to the success of any software project. The quality of documentation can be even more important than the quality of the code itself, as a good first impression will prompt developers to look further into your code. phpDocumentor is designed to make it easier to create documentation. phpDocumentor even makes it possible to generate separate sets of documentation from the same source!

Writing Great Documentation

Consider the audience.

The first question any writer must ask is "Who is my audience?" This will answer many questions. For most software, such as any MS product, the software is intended only to be used. The programmers are the only people who have access to the source code. The challenge in this case is to write good documentation for end-users.

When writing documentation for an open-source project intending to be both used and extended, this challenge is magnified by the fact that many people will also intend to extend the source, or even find obscure bugs and fix them. These two audiences tend to be opposed to each other in their needs.

Instruction-style writing, that explains and describes general concepts more than how a particular variable is used

Interface information only, no low-level details

Examples of how to use, and tutorials

Details on how program elements interact, which elements use others

Where in the source code an action or series of actions occurs

How to extend the code to add new functionality

These two kinds of users can not be serviced by just API documentation or just tutorials, but a subtle blend of the two.

Using phpDocumentor to make documentation for two separate audiences

In essence, there may need to be two separate sets of documentation! phpDocumentor can be used to create this option using a few things. First, using the command-line file-selection options, one can write two sets of documentation, one for end-users, and the other for programmers, and put them in different subdirectories. For instance, one could put enduser docs in "enduser/tutorials" and programmer docs in "programmer/tutorials." In addition, using the @access tag, one can mark programmer-level elements with @access private, and they will be ignored by default. The @internal tag and inline {@internal}} inline tag construct can be used to mark documentation that is low-level or internal to a smaller audience of developers. When creating programmer documentation, turn on the parse private option (see -pp, --parseprivate ), and the low-level detail will be generated.

More important, the in-code documents in your DocBlocks must be written for both end-users and programmers wherever possible.

phpDocumentor uses the chaining feature of tutorials to link together related documentation like chapters in a book, and this is another way to organize documentation. Experiment, and find what's best for your project's needs.

Tips on Revising

There are many ways of creating good documentation, but perhaps the best is to read what you have written from different perspectives. Open up your documentation, and try to use it to figure out your software project. If this is difficult, go back and edit or rewrite. Remove anything that is confusing or unnecessary, make sure everything is there that is needed, and then when it seems good, ask a php user that doesn't know your project, or even a non-programmer to read it and use their reactions to tailor the documentation.

The use of phpDocumentor will definitely improve the look and feel of your documentation, but don't stop there, let it help you to create truly dynamic documents that are easily maintained and kept up-to-date. After all, great docs for great programs will help to secure PHP's rightful throne as the best out there!

References for learning how to use phpDocumentor

phpDocumentor Quickstart

  • Skip to main content
  • Skip to search
  • Sign up for free

how to write php documentation

Creating effective technical documentation

Author avatar

Effective feature documentation is important in enhancing a user's experience with the feature. Good documentation is like a piece of the puzzle that makes everything click — the key for encouraging feature adoption.

To support you in creating effective technical documentation, this article provides an overview of the core principles of technical writing. It also highlights the best practices for creating clear and accessible documentation. Applying these technical writing principles helps us maintain the high quality of content on MDN. Whether you're documenting your own project or product or contributing to technical content in various settings, you can improve the quality of your work by following these best practices.

Adopt clarity, conciseness, and consistency

These three Cs form the core principles of technical writing. They can take you a long way in producing quality documentation.

For achieving clarity in your writing, apply the following guidelines:

  • Use simple words and clear language. Keep in mind the audience, especially if it includes non-native English speakers.
  • Be clear about who needs to perform the action. Writing in active voice is not strictly required. However, you should use it when you want to be clear about who needs to perform the action. For example, clarify whether a function is triggered by an event or if the user needs to explicitly call the function.
  • Clearly introduce and explain new terms. This helps to lay the foundation for concepts that are covered later in the documentation.
Tip : Replace "it", "this", and "these" with proper nouns if they can refer to more than one thing in the given context.
  • Aim for one idea per sentence to improve readability.
  • Stick to one main idea per paragraph. Each sentence in a paragraph should logically connect to the one before it. Imagine if each sentence in a paragraph was a link in a chain. If you pick up the first link, the other links in the chain should follow, forming a continuous sequence. This is how the sentences should connect to each other, ensuring a seamless flow of a single idea.


Keep sentences short. This automatically increases the readability and clarity of your document. It also helps in quick comprehension. Long sentences can be more challenging to understand quickly due to their complex structures.

Tip : Based on common readability standards, aim for 15-20 words per sentence.

For additional insights on sentence length and readability strategies, see Simple sentences (on ) and Popular readability formulas , including the Flesch-Kincaid index, on Wikipedia.


Use the same terminology throughout your documentation to ensure a seamless reader experience. For example, if you start referring to "user agents" as browsers, stick with that term consistently. This avoids confusion that can arise from using words interchangeably, even when they share the same meaning.

Additionally, maintain consistent word casing and follow a uniform formatting style throughout your documentation. These practices not only enhance readability but also contribute to a professional presentation of your documentation.

Organize your content for maximum impact

Apply the same principles for organizing your content as you would for organizing your code: spend some time setting a clear goal and thinking about the desired structure for your documentation. Ensure that each subsection contributes to this goal incrementally.

Start with an introduction

In the introduction, first describe the feature you're documenting. Next, set the context by explaining why learning about the feature would be beneficial to the readers. This can include describing real-life scenarios where the feature can be useful. The more relevance you add to the topic, the easier it will be for readers to understand and engage with the content.

Progress logically

The following questions can help you ensure that your content is progressing logically:

  • Is your document structured to guide readers from foundational concepts to more advanced ones? Are there sections to introduce the " what " to establish a base before delving into the " why " and " how "? Consider whether the document structure mirrors the natural learning path for the topic. Aligning the document's structure with the natural progression of learning helps readers build their knowledge step-by-step and also enhances the overall learning experience.
  • Are there sufficient how-to guides or examples following the conceptual sections?
  • Consider the flow of the content. Is it following a logical sequence — from one sentence to the next, from one paragraph to the next, and from one section to the next? Does each section logically build on the information presented previously, avoiding abrupt jumps or gaps in the content?

Additionally, as you work on the draft, always ask yourself:

  • What reader questions am I addressing with this sentence?
  • Can I add a simplistic or real-life use case to explain this concept?

Include examples

Imagine sitting next to someone as you explain the concepts to them. Preempt their questions and address them in your writing. Use this approach to add as many relevant examples as possible.

When adding examples, don't restrict yourself to only code; include non-code scenarios to demonstrate a feature's utility. This helps readers understand the concepts better and also caters to different learning styles. Consider providing real-world scenarios or use cases to illustrate how the feature or concept applies in practical situations.

Optimize the document structure and length

Evaluate your documentation's structure to ensure it maintains a logical and balanced hierarchy.

  • Ensure that each section and subsection has a clear purpose and sufficient content.
  • Look for instances where a main section contains only one subsection (orphan), such as a single H3 section under an H2 section. This indicates that you need to reorganize your content or make some additions.
  • Check if there are lower-level headings such as H4 . Too many subsections can be overwhelming for readers, making it difficult for them to grasp the information. In such cases, consider presenting the content as a bulleted list instead to help readers retain the key points more effectively. This approach helps to simplify the hierarchy and also contributes to easier navigation.
  • While there should be sufficient content for each section, pay attention to the overall length. If any section becomes too extensive, it can be overwhelming for readers. Split large sections into multiple logical subsections or restructure the content into new sections and subsections. Grouping content into digestible pieces helps maintain focus and improve navigation for readers.

Proofread your writing

One aspect that cannot be stressed enough is the importance of self-reviewing and proofreading what you've written. Whether you're creating a large document or a short paragraph, this step is crucial.

Taking the time to fully review your work will help you identify sections that don't flow well or can be improved for clarity. During self-review, aim to spot and remove redundancy (repetition of ideas without adding value) and repetitiveness (overuse of words or phrases). These refinements will ensure your documentation is clear and coherent and conveys your ideas as intended.

Proofread and then take a break before you review again. Only then submit your work. While spell checkers can flag spelling errors, they might not flag incorrect use of words, such as an unintended use of "he" instead of "the". It's best to take a break and return with fresh eyes to catch any errors you might have missed. Pay close attention to identify inconsistencies in tone, style, tense, or formatting and make the necessary adjustments.

Additional tips

To improve the clarity and accessibility of your documentation, also keep the following guidelines and tips in mind. To go in-depth into any of the topics, feel free to consult our Writing style guide .

  • Bulleted vs numbered lists : Lists, in general, make documentation easier to scan. Use bulleted lists when there is no specific order of the items. Use numbered lists when the steps need to be followed in the specific order. Always include a lead-sentence before beginning a list to provide context.
  • Commas : Use a comma after an introductory clause to improve readability and to clarify the sentence structure. Use a comma to separate items in a list to ensure clarity.
  • Alt text : Always provide an alternative text for the images you add to content. This makes your documentation accessible to people using screen readers. In addition to images, ensure that video and audio files have accompanying descriptive texts.
  • Descriptive link text : Make sure each link text is clear even out of context and clearly indicates where the link leads. Descriptive link texts also help people using screen readers understand the destination of links. For example, use "Read our writing style guide to learn more" instead of "Click here to learn more".
  • Inclusive language : Make your documentation welcoming to everyone. Strive to use words that respect and acknowledge the diversity of your audience.

That's it for this article. I hope you found these tips helpful as a quick refresher on technical writing best practices. Remember that learning how to create effective and easy-to-use documentation is an ongoing process. It starts with understanding your audience and the goals of your documentation. By applying these technical writing principles and tips, you'll certainly be able to enhance the clarity and overall quality of your documentation.

Let me know if you learned something new or if there's any idea that resonated with you. I'd also like to hear if there are any best practices you use in your technical documentation workflow. Share with us on Mastodon or Discord .

Previous Post Leveraging Bun on Vultr: A superior Node.js alternative

Stay informed with mdn.

Get the MDN newsletter and never miss an update on the latest web development trends, tips, and best practices.

Key Features


More Features


  • All Connectors →


By Use Case


  • All Use Cases →

By Industry


  • All Industries →

Learn About Dataedo


Learn About Data


After Hours


  • Book a demo Try Dataedo

How to document REST API project written in PHP using Swagger and Dataedo

Wojciech Mleczek - Dataedo Team

  • 18th August, 2017

how to write php documentation

Writing REST API in mostly focused on planning the interface which is later accessed using curl, js, other backend systems or event mobile and desktop applications. The problem with REST API is that is not the official standard comparing to the GraphQL (relatively new offer from facebook) or Web Services (SOAP) . Of course, there're many nonwritten standards like using limit and fields query params or frequently forgotten HATEOAS .

Why documenting interfaces is so important?

The main role of the interfaces is to abstract some business logic from the implementation . These interfaces are used to communicate with other objects or even humans. They don't focus on some deep implementation related issues but describes how we interact with the surrounding world which is highly important. If we know how the interface communicates with the world, we can even rewrite the whole module without worrying that something could break (of course tests also will be very welcome).

Assume we have many small interfaces to manage users, orders, invoices and so one. Each one is independent from the other and can be implemented as a separate REST API , GraphQL or Web Service (SOAP) endpoint. This is what many people call microservices . This kind of architecture doesn't need detailed documentation of the implementation. The clue is to document the interface - commands, queries, requests, responses. It is because one of the ideas behind microservices is that we can reimplement them in a few days (which could be hard if we miss documentation, specified use cases, and integration tests).

Is database schema an interface or an internal structure?

The keyword to answer this question is Big Data . By many, it's treated as a buzzword, but in this case, it is not important. The truth is that companies more often collect data from all sources , analyze them and draw conclusions which will be used to improve business workflow. Of course, many developers still think that database is an integral part of the application which is not the truth. Sooner or later one of the data analysts desires to get data also from your database. Good documentation will definitely help you to get some new friends or at least maintain the good name. Summarizing database is a kind of the interface between developers and data analysts and therefore also needs to be documented.

Documenting REST API without much effort - is it possible?

Let's start with some examples. I'll explain the basics of the swagger and show you how to generate user-friendly documentation without writing a line of "truth" PHP code.

Step 1 - Initialize composer.json and require the zircote/swagger-php library. We also add script to generate swagger.json file which will be later used to open HTML documentation.

Step 2 - Write example API documentation. Note that we write comments in the plain PHP file. In the real world, the comments would be placed above the methods, which implement REST API endpoints. It's important to place the below file in the src directory because in the composer docs script we specified that swagger has to scan all files in the src directory (e.g., it could be named src/hello-api-documentation.php ).

Step 3 - Now if you run composer run docs you should see:

Step 4 - Open the online Swagger Editor and go to File -> Import file and select generated swagger.json file. Now it doesn't look impressive, but you can see example Petstore documentation . Of course, you can host this documentation on your own server.

Example Swagger Editor Documentation

More advanced examples can be found in the official library documentation .

Can generating database documentation can be as simple as using Swagger?

I'm suggesting to give a chance our Dataedo product which gives you a possibility to document database structure. Generated documentation keep in sync with database changes. Your role is only to write meaningful comments for tables, columns or even user-defined modules. It is going to help keep database structure clear for huge databases with 100 or more objects.

Step 1 - Download the Lite version of Dataedo completely for free and create file repository (uncheck the "Include samples" option in the next step):

Dataedo Welcome Screen

Step 2 - Click Add documentation and connect to your database. Try to go through all the steps by yourself. You don't have to worry about your database - the process of importing database performs only read operations .

Dataedo Add Documentation

Step 3 - Add some comments and start creating something truly amazing - generate documentation using only a few click. Pick the Export documentation option, choose the output format ( get free trial to give a try other formats). You can check the PDF format in the Dataedo Lite Edition, so I'll show you the new HTML template (which still is in development - will be available in Dataedo 6 ).

New Dataedo HTML Template

More advanced details can be found in the official Dataedo documentation .


You Don't Need an ER Diagram to Understand Your Database

You Don't Need an ER Diagram to Understand Your Database

Mass update/export of documentation of multiple databases in Dataedo

Mass update/export of documentation of multiple databases in Dataedo

Is Lack of Database Documentation a Global Problem for Software Developers?

Is Lack of Database Documentation a Global Problem for Software Developers?

PHP 101

How to Write PHP Comments (and best practices) - How to Write PHP Comments (and best practices) - How to Write PHP Comments (and best practices)

Do you feel good looking at PHP projects with thousands of classes, and functions without knowing what they do? Or even just a few lines of codes but you quickly forgot what the previous lines do? Well, I did. That’s why you should know how to write PHP comments, and – I mean, do it the right way.

You can quickly write PHP comments by three methods:

  • Use double forward slashes: // This method is only used for  single-line   comments .
  • Forward slash and asterisk – Block type: /* (open) and  */ (close) This method can be used for both  single-line and  multiline comments .
  • Use hash sign:  # Similar to forward slashes, this method can be used for single-line comments .

Quick PHP comments example:

And the comment won’t be outputted to the user:

That’s all the basic tips you need for writing PHP comments.

Below are other tips to know for getting your PHP comments written properly, and following PHP coding standards.

What are PHP comments and why should we write comments?

Like any other programming language, PHP comment helps organize your PHP project code structure for better understanding and debugging purposes, and also adds explanation and clarification to the other PHP developers looking at your code.

For example, do you want your PHP codes (or somebody’s codes) to look like this?

Or should it be like this?

Of course, these are just dummy codes, but imagine a project with thousand of lines of codes, functions, classes, it would be a real nightmare without any comments to tell the developer what is everything.

Having clear PHP comments is highly recommended, especially in your public GitHub projects, or company/team PHP projects which is a must.

Best practices to write PHP comments

Although PHP comments can be written the way you preferred, to follow PHP coding standards and make it developer friendly, there are several recommended guidelines when writing comments in PHP projects:

1. Use forward slashes // for single-line comments

Single-line comments should be used by forward slashes method:

2. Use forward slash + asterisk (block type) /* */ for multiline comments

Multiline comments should be used by slash + asterisk method:

3. Use block type /* */ for header comments

Header comments are the starting comments of a PHP file to clarify the content to the developer.

4. Use block type /* */ as DocBlock format to document PHP functions and classes

DocBlock is an adaptation of Javadoc for PHP programming, it allows external document generators and PHP IDEs to interpret variable types for providing code completion, type hinting, and debugging.

5. Comments should be on their own line

That’s all about general recommendations and tips for writing PHP comments in PHP development. This article could be updated later in case of new information, or when it should be revised.

Happy coding!

You might be interested in…

How to add elements to array in php easily.

  • PHP comments on the official PHP Documentation website
  • PHPDoc and DocBlock on Wikipedia

4 ways to increase PHP memory limit

Related posts. - How to set timezone with PHP

How to set timezone with PHP easily (multiple methods) - How to redirect to another page using PHP

How to redirect to another page using PHP

Table of contents.

PHP101.Net - How to increase PHP memory limit

We deliver free and helpful resources for learning and using PHP programming language.

How to change Laragon PHP version on Windows

How to convert from string to array in php, how to convert image to base64 using php, how to install composer on linux.

© 2022 PHP101.Net - Helpful PHP Tutorials, How-to, Tips and Tricks for everyone.

© 2022 PHP101.Net - Helpful PHP Tutorials, How-to, Tips and Tricks for everyone. | Privacy Policy

Blade Templates

Supercharging blade with livewire, html entity encoding, blade and javascript frameworks, if statements, switch statements, the loop variable.

  • Conditional Classes

Additional Attributes

Including subviews, the @once directive, rendering components, passing data to components, component attributes, reserved keywords, inline component views, dynamic components, manually registering components, anonymous index components, data properties / attributes, accessing parent data.

  • Anonymous Components Paths

Layouts Using Components

Layouts using template inheritance, method field, validation errors, service injection, rendering inline blade templates, rendering blade fragments, custom echo handlers, custom if statements, introduction.

Blade is the simple, yet powerful templating engine that is included with Laravel. Unlike some PHP templating engines, Blade does not restrict you from using plain PHP code in your templates. In fact, all Blade templates are compiled into plain PHP code and cached until they are modified, meaning Blade adds essentially zero overhead to your application. Blade template files use the .blade.php file extension and are typically stored in the resources/views directory.

Blade views may be returned from routes or controllers using the global view helper. Of course, as mentioned in the documentation on views , data may be passed to the Blade view using the view helper's second argument:

Want to take your Blade templates to the next level and build dynamic interfaces with ease? Check out Laravel Livewire . Livewire allows you to write Blade components that are augmented with dynamic functionality that would typically only be possible via frontend frameworks like React or Vue, providing a great approach to building modern, reactive frontends without the complexities, client-side rendering, or build steps of many JavaScript frameworks.

Displaying Data

You may display data that is passed to your Blade views by wrapping the variable in curly braces. For example, given the following route:

You may display the contents of the name variable like so:

[!NOTE] Blade's {{ }} echo statements are automatically sent through PHP's htmlspecialchars function to prevent XSS attacks.

You are not limited to displaying the contents of the variables passed to the view. You may also echo the results of any PHP function. In fact, you can put any PHP code you wish inside of a Blade echo statement:

By default, Blade (and the Laravel e function) will double encode HTML entities. If you would like to disable double encoding, call the Blade::withoutDoubleEncoding method from the boot method of your AppServiceProvider :

Displaying Unescaped Data

By default, Blade {{ }} statements are automatically sent through PHP's htmlspecialchars function to prevent XSS attacks. If you do not want your data to be escaped, you may use the following syntax:

[!WARNING] Be very careful when echoing content that is supplied by users of your application. You should typically use the escaped, double curly brace syntax to prevent XSS attacks when displaying user supplied data.

Since many JavaScript frameworks also use "curly" braces to indicate a given expression should be displayed in the browser, you may use the @ symbol to inform the Blade rendering engine an expression should remain untouched. For example:

In this example, the @ symbol will be removed by Blade; however, {{ name }} expression will remain untouched by the Blade engine, allowing it to be rendered by your JavaScript framework.

The @ symbol may also be used to escape Blade directives:

Rendering JSON

Sometimes you may pass an array to your view with the intention of rendering it as JSON in order to initialize a JavaScript variable. For example:

However, instead of manually calling json_encode , you may use the Illuminate\Support\Js::from method directive. The from method accepts the same arguments as PHP's json_encode function; however, it will ensure that the resulting JSON is properly escaped for inclusion within HTML quotes. The from method will return a string JSON.parse JavaScript statement that will convert the given object or array into a valid JavaScript object:

The latest versions of the Laravel application skeleton include a Js facade, which provides convenient access to this functionality within your Blade templates:

[!WARNING] You should only use the Js::from method to render existing variables as JSON. The Blade templating is based on regular expressions and attempts to pass a complex expression to the directive may cause unexpected failures.

The @verbatim Directive

If you are displaying JavaScript variables in a large portion of your template, you may wrap the HTML in the @verbatim directive so that you do not have to prefix each Blade echo statement with an @ symbol:

Blade Directives

In addition to template inheritance and displaying data, Blade also provides convenient shortcuts for common PHP control structures, such as conditional statements and loops. These shortcuts provide a very clean, terse way of working with PHP control structures while also remaining familiar to their PHP counterparts.

You may construct if statements using the @if , @elseif , @else , and @endif directives. These directives function identically to their PHP counterparts:

For convenience, Blade also provides an @unless directive:

In addition to the conditional directives already discussed, the @isset and @empty directives may be used as convenient shortcuts for their respective PHP functions:

Authentication Directives

The @auth and @guest directives may be used to quickly determine if the current user is authenticated or is a guest:

If needed, you may specify the authentication guard that should be checked when using the @auth and @guest directives:

Environment Directives

You may check if the application is running in the production environment using the @production directive:

Or, you may determine if the application is running in a specific environment using the @env directive:

Section Directives

You may determine if a template inheritance section has content using the @hasSection directive:

You may use the sectionMissing directive to determine if a section does not have content:

Session Directives

The @session directive may be used to determine if a session value exists. If the session value exists, the template contents within the @session and @endsession directives will be evaluated. Within the @session directive's contents, you may echo the $value variable to display the session value:

Switch statements can be constructed using the @switch , @case , @break , @default and @endswitch directives:

In addition to conditional statements, Blade provides simple directives for working with PHP's loop structures. Again, each of these directives functions identically to their PHP counterparts:

[!NOTE] While iterating through a foreach loop, you may use the loop variable to gain valuable information about the loop, such as whether you are in the first or last iteration through the loop.

When using loops you may also skip the current iteration or end the loop using the @continue and @break directives:

You may also include the continuation or break condition within the directive declaration:

While iterating through a foreach loop, a $loop variable will be available inside of your loop. This variable provides access to some useful bits of information such as the current loop index and whether this is the first or last iteration through the loop:

If you are in a nested loop, you may access the parent loop's $loop variable via the parent property:

The $loop variable also contains a variety of other useful properties:

Conditional Classes & Styles

The @class directive conditionally compiles a CSS class string. The directive accepts an array of classes where the array key contains the class or classes you wish to add, while the value is a boolean expression. If the array element has a numeric key, it will always be included in the rendered class list:

Likewise, the @style directive may be used to conditionally add inline CSS styles to an HTML element:

For convenience, you may use the @checked directive to easily indicate if a given HTML checkbox input is "checked". This directive will echo checked if the provided condition evaluates to true :

Likewise, the @selected directive may be used to indicate if a given select option should be "selected":

Additionally, the @disabled directive may be used to indicate if a given element should be "disabled":

Moreover, the @readonly directive may be used to indicate if a given element should be "readonly":

In addition, the @required directive may be used to indicate if a given element should be "required":

[!NOTE] While you're free to use the @include directive, Blade components provide similar functionality and offer several benefits over the @include directive such as data and attribute binding.

Blade's @include directive allows you to include a Blade view from within another view. All variables that are available to the parent view will be made available to the included view:

Even though the included view will inherit all data available in the parent view, you may also pass an array of additional data that should be made available to the included view:

If you attempt to @include a view which does not exist, Laravel will throw an error. If you would like to include a view that may or may not be present, you should use the @includeIf directive:

If you would like to @include a view if a given boolean expression evaluates to true or false , you may use the @includeWhen and @includeUnless directives:

To include the first view that exists from a given array of views, you may use the includeFirst directive:

[!WARNING] You should avoid using the __DIR__ and __FILE__ constants in your Blade views, since they will refer to the location of the cached, compiled view.

Rendering Views for Collections

You may combine loops and includes into one line with Blade's @each directive:

The @each directive's first argument is the view to render for each element in the array or collection. The second argument is the array or collection you wish to iterate over, while the third argument is the variable name that will be assigned to the current iteration within the view. So, for example, if you are iterating over an array of jobs , typically you will want to access each job as a job variable within the view. The array key for the current iteration will be available as the key variable within the view.

You may also pass a fourth argument to the @each directive. This argument determines the view that will be rendered if the given array is empty.

[!WARNING] Views rendered via @each do not inherit the variables from the parent view. If the child view requires these variables, you should use the @foreach and @include directives instead.

The @once directive allows you to define a portion of the template that will only be evaluated once per rendering cycle. This may be useful for pushing a given piece of JavaScript into the page's header using stacks . For example, if you are rendering a given component within a loop, you may wish to only push the JavaScript to the header the first time the component is rendered:

Since the @once directive is often used in conjunction with the @push or @prepend directives, the @pushOnce and @prependOnce directives are available for your convenience:

In some situations, it's useful to embed PHP code into your views. You can use the Blade @php directive to execute a block of plain PHP within your template:

Or, if you only need to use PHP to import a class, you may use the @use directive:

A second argument may be provided to the @use directive to alias the imported class:

Blade also allows you to define comments in your views. However, unlike HTML comments, Blade comments are not included in the HTML returned by your application:

Components and slots provide similar benefits to sections, layouts, and includes; however, some may find the mental model of components and slots easier to understand. There are two approaches to writing components: class based components and anonymous components.

To create a class based component, you may use the make:component Artisan command. To illustrate how to use components, we will create a simple Alert component. The make:component command will place the component in the app/View/Components directory:

The make:component command will also create a view template for the component. The view will be placed in the resources/views/components directory. When writing components for your own application, components are automatically discovered within the app/View/Components directory and resources/views/components directory, so no further component registration is typically required.

You may also create components within subdirectories:

The command above will create an Input component in the app/View/Components/Forms directory and the view will be placed in the resources/views/components/forms directory.

If you would like to create an anonymous component (a component with only a Blade template and no class), you may use the --view flag when invoking the make:component command:

The command above will create a Blade file at resources/views/components/forms/input.blade.php which can be rendered as a component via <x-forms.input /> .

Manually Registering Package Components

When writing components for your own application, components are automatically discovered within the app/View/Components directory and resources/views/components directory.

However, if you are building a package that utilizes Blade components, you will need to manually register your component class and its HTML tag alias. You should typically register your components in the boot method of your package's service provider:

Once your component has been registered, it may be rendered using its tag alias:

Alternatively, you may use the componentNamespace method to autoload component classes by convention. For example, a Nightshade package might have Calendar and ColorPicker components that reside within the Package\Views\Components namespace:

This will allow the usage of package components by their vendor namespace using the package-name:: syntax:

Blade will automatically detect the class that's linked to this component by pascal-casing the component name. Subdirectories are also supported using "dot" notation.

To display a component, you may use a Blade component tag within one of your Blade templates. Blade component tags start with the string x- followed by the kebab case name of the component class:

If the component class is nested deeper within the app/View/Components directory, you may use the . character to indicate directory nesting. For example, if we assume a component is located at app/View/Components/Inputs/Button.php , we may render it like so:

If you would like to conditionally render your component, you may define a shouldRender method on your component class. If the shouldRender method returns false the component will not be rendered:

You may pass data to Blade components using HTML attributes. Hard-coded, primitive values may be passed to the component using simple HTML attribute strings. PHP expressions and variables should be passed to the component via attributes that use the : character as a prefix:

You should define all of the component's data attributes in its class constructor. All public properties on a component will automatically be made available to the component's view. It is not necessary to pass the data to the view from the component's render method:

When your component is rendered, you may display the contents of your component's public variables by echoing the variables by name:

Component constructor arguments should be specified using camelCase , while kebab-case should be used when referencing the argument names in your HTML attributes. For example, given the following component constructor:

The $alertType argument may be provided to the component like so:

Short Attribute Syntax

When passing attributes to components, you may also use a "short attribute" syntax. This is often convenient since attribute names frequently match the variable names they correspond to:

Escaping Attribute Rendering

Since some JavaScript frameworks such as Alpine.js also use colon-prefixed attributes, you may use a double colon ( :: ) prefix to inform Blade that the attribute is not a PHP expression. For example, given the following component:

The following HTML will be rendered by Blade:

Component Methods

In addition to public variables being available to your component template, any public methods on the component may be invoked. For example, imagine a component that has an isSelected method:

You may execute this method from your component template by invoking the variable matching the name of the method:

Accessing Attributes and Slots Within Component Classes

Blade components also allow you to access the component name, attributes, and slot inside the class's render method. However, in order to access this data, you should return a closure from your component's render method. The closure will receive a $data array as its only argument. This array will contain several elements that provide information about the component:

The componentName is equal to the name used in the HTML tag after the x- prefix. So <x-alert /> 's componentName will be alert . The attributes element will contain all of the attributes that were present on the HTML tag. The slot element is an Illuminate\Support\HtmlString instance with the contents of the component's slot.

The closure should return a string. If the returned string corresponds to an existing view, that view will be rendered; otherwise, the returned string will be evaluated as an inline Blade view.

Additional Dependencies

If your component requires dependencies from Laravel's service container , you may list them before any of the component's data attributes and they will automatically be injected by the container:

Hiding Attributes / Methods

If you would like to prevent some public methods or properties from being exposed as variables to your component template, you may add them to an $except array property on your component:

We've already examined how to pass data attributes to a component; however, sometimes you may need to specify additional HTML attributes, such as class , that are not part of the data required for a component to function. Typically, you want to pass these additional attributes down to the root element of the component template. For example, imagine we want to render an alert component like so:

All of the attributes that are not part of the component's constructor will automatically be added to the component's "attribute bag". This attribute bag is automatically made available to the component via the $attributes variable. All of the attributes may be rendered within the component by echoing this variable:

[!WARNING] Using directives such as @env within component tags is not supported at this time. For example, <x-alert :live="@env('production')"/> will not be compiled.

Default / Merged Attributes

Sometimes you may need to specify default values for attributes or merge additional values into some of the component's attributes. To accomplish this, you may use the attribute bag's merge method. This method is particularly useful for defining a set of default CSS classes that should always be applied to a component:

If we assume this component is utilized like so:

The final, rendered HTML of the component will appear like the following:

Conditionally Merge Classes

Sometimes you may wish to merge classes if a given condition is true . You can accomplish this via the class method, which accepts an array of classes where the array key contains the class or classes you wish to add, while the value is a boolean expression. If the array element has a numeric key, it will always be included in the rendered class list:

If you need to merge other attributes onto your component, you can chain the merge method onto the class method:

[!NOTE] If you need to conditionally compile classes on other HTML elements that shouldn't receive merged attributes, you can use the @class directive .

Non-Class Attribute Merging

When merging attributes that are not class attributes, the values provided to the merge method will be considered the "default" values of the attribute. However, unlike the class attribute, these attributes will not be merged with injected attribute values. Instead, they will be overwritten. For example, a button component's implementation may look like the following:

To render the button component with a custom type , it may be specified when consuming the component. If no type is specified, the button type will be used:

The rendered HTML of the button component in this example would be:

If you would like an attribute other than class to have its default value and injected values joined together, you may use the prepends method. In this example, the data-controller attribute will always begin with profile-controller and any additional injected data-controller values will be placed after this default value:

Retrieving and Filtering Attributes

You may filter attributes using the filter method. This method accepts a closure which should return true if you wish to retain the attribute in the attribute bag:

For convenience, you may use the whereStartsWith method to retrieve all attributes whose keys begin with a given string:

Conversely, the whereDoesntStartWith method may be used to exclude all attributes whose keys begin with a given string:

Using the first method, you may render the first attribute in a given attribute bag:

If you would like to check if an attribute is present on the component, you may use the has method. This method accepts the attribute name as its only argument and returns a boolean indicating whether or not the attribute is present:

If an array is passed to the has method, the method will determine if all of the given attributes are present on the component:

The hasAny method may be used to determine if any of the given attributes are present on the component:

You may retrieve a specific attribute's value using the get method:

By default, some keywords are reserved for Blade's internal use in order to render components. The following keywords cannot be defined as public properties or method names within your components:

  • resolveView
  • shouldRender
  • withAttributes

You will often need to pass additional content to your component via "slots". Component slots are rendered by echoing the $slot variable. To explore this concept, let's imagine that an alert component has the following markup:

We may pass content to the slot by injecting content into the component:

Sometimes a component may need to render multiple different slots in different locations within the component. Let's modify our alert component to allow for the injection of a "title" slot:

You may define the content of the named slot using the x-slot tag. Any content not within an explicit x-slot tag will be passed to the component in the $slot variable:

You may invoke a slot's isEmpty method to determine if the slot contains content:

Additionally, the hasActualContent method may be used to determine if the slot contains any "actual" content that is not an HTML comment:

Scoped Slots

If you have used a JavaScript framework such as Vue, you may be familiar with "scoped slots", which allow you to access data or methods from the component within your slot. You may achieve similar behavior in Laravel by defining public methods or properties on your component and accessing the component within your slot via the $component variable. In this example, we will assume that the x-alert component has a public formatAlert method defined on its component class:

Slot Attributes

Like Blade components, you may assign additional attributes to slots such as CSS class names:

To interact with slot attributes, you may access the attributes property of the slot's variable. For more information on how to interact with attributes, please consult the documentation on component attributes :

For very small components, it may feel cumbersome to manage both the component class and the component's view template. For this reason, you may return the component's markup directly from the render method:

Generating Inline View Components

To create a component that renders an inline view, you may use the inline option when executing the make:component command:

Sometimes you may need to render a component but not know which component should be rendered until runtime. In this situation, you may use Laravel's built-in dynamic-component component to render the component based on a runtime value or variable:

[!WARNING] The following documentation on manually registering components is primarily applicable to those who are writing Laravel packages that include view components. If you are not writing a package, this portion of the component documentation may not be relevant to you.

However, if you are building a package that utilizes Blade components or placing components in non-conventional directories, you will need to manually register your component class and its HTML tag alias so that Laravel knows where to find the component. You should typically register your components in the boot method of your package's service provider:

Autoloading Package Components

Anonymous components.

Similar to inline components, anonymous components provide a mechanism for managing a component via a single file. However, anonymous components utilize a single view file and have no associated class. To define an anonymous component, you only need to place a Blade template within your resources/views/components directory. For example, assuming you have defined a component at resources/views/components/alert.blade.php , you may simply render it like so:

You may use the . character to indicate if a component is nested deeper inside the components directory. For example, assuming the component is defined at resources/views/components/inputs/button.blade.php , you may render it like so:

Sometimes, when a component is made up of many Blade templates, you may wish to group the given component's templates within a single directory. For example, imagine an "accordion" component with the following directory structure:

This directory structure allows you to render the accordion component and its item like so:

However, in order to render the accordion component via x-accordion , we were forced to place the "index" accordion component template in the resources/views/components directory instead of nesting it within the accordion directory with the other accordion related templates.

Thankfully, Blade allows you to place an index.blade.php file within a component's template directory. When an index.blade.php template exists for the component, it will be rendered as the "root" node of the component. So, we can continue to use the same Blade syntax given in the example above; however, we will adjust our directory structure like so:

Since anonymous components do not have any associated class, you may wonder how you may differentiate which data should be passed to the component as variables and which attributes should be placed in the component's attribute bag .

You may specify which attributes should be considered data variables using the @props directive at the top of your component's Blade template. All other attributes on the component will be available via the component's attribute bag. If you wish to give a data variable a default value, you may specify the variable's name as the array key and the default value as the array value:

Given the component definition above, we may render the component like so:

Sometimes you may want to access data from a parent component inside a child component. In these cases, you may use the @aware directive. For example, imagine we are building a complex menu component consisting of a parent <x-menu> and child <x-menu.item> :

The <x-menu> component may have an implementation like the following:

Because the color prop was only passed into the parent ( <x-menu> ), it won't be available inside <x-menu.item> . However, if we use the @aware directive, we can make it available inside <x-menu.item> as well:

[!WARNING] The @aware directive can not access parent data that is not explicitly passed to the parent component via HTML attributes. Default @props values that are not explicitly passed to the parent component can not be accessed by the @aware directive.

Anonymous Component Paths

As previously discussed, anonymous components are typically defined by placing a Blade template within your resources/views/components directory. However, you may occasionally want to register other anonymous component paths with Laravel in addition to the default path.

The anonymousComponentPath method accepts the "path" to the anonymous component location as its first argument and an optional "namespace" that components should be placed under as its second argument. Typically, this method should be called from the boot method of one of your application's service providers :

When component paths are registered without a specified prefix as in the example above, they may be rendered in your Blade components without a corresponding prefix as well. For example, if a panel.blade.php component exists in the path registered above, it may be rendered like so:

Prefix "namespaces" may be provided as the second argument to the anonymousComponentPath method:

When a prefix is provided, components within that "namespace" may be rendered by prefixing to the component's namespace to the component name when the component is rendered:

Building Layouts

Most web applications maintain the same general layout across various pages. It would be incredibly cumbersome and hard to maintain our application if we had to repeat the entire layout HTML in every view we create. Thankfully, it's convenient to define this layout as a single Blade component and then use it throughout our application.

Defining the Layout Component

For example, imagine we are building a "todo" list application. We might define a layout component that looks like the following:

Applying the Layout Component

Once the layout component has been defined, we may create a Blade view that utilizes the component. In this example, we will define a simple view that displays our task list:

Remember, content that is injected into a component will be supplied to the default $slot variable within our layout component. As you may have noticed, our layout also respects a $title slot if one is provided; otherwise, a default title is shown. We may inject a custom title from our task list view using the standard slot syntax discussed in the component documentation :

Now that we have defined our layout and task list views, we just need to return the task view from a route:

Defining a Layout

Layouts may also be created via "template inheritance". This was the primary way of building applications prior to the introduction of components .

To get started, let's take a look at a simple example. First, we will examine a page layout. Since most web applications maintain the same general layout across various pages, it's convenient to define this layout as a single Blade view:

As you can see, this file contains typical HTML mark-up. However, take note of the @section and @yield directives. The @section directive, as the name implies, defines a section of content, while the @yield directive is used to display the contents of a given section.

Now that we have defined a layout for our application, let's define a child page that inherits the layout.

Extending a Layout

When defining a child view, use the @extends Blade directive to specify which layout the child view should "inherit". Views which extend a Blade layout may inject content into the layout's sections using @section directives. Remember, as seen in the example above, the contents of these sections will be displayed in the layout using @yield :

In this example, the sidebar section is utilizing the @parent directive to append (rather than overwriting) content to the layout's sidebar. The @parent directive will be replaced by the content of the layout when the view is rendered.

[!NOTE] Contrary to the previous example, this sidebar section ends with @endsection instead of @show . The @endsection directive will only define a section while @show will define and immediately yield the section.

The @yield directive also accepts a default value as its second parameter. This value will be rendered if the section being yielded is undefined:

Anytime you define an HTML form in your application, you should include a hidden CSRF token field in the form so that the CSRF protection middleware can validate the request. You may use the @csrf Blade directive to generate the token field:

Since HTML forms can't make PUT , PATCH , or DELETE requests, you will need to add a hidden _method field to spoof these HTTP verbs. The @method Blade directive can create this field for you:

The @error directive may be used to quickly check if validation error messages exist for a given attribute. Within an @error directive, you may echo the $message variable to display the error message:

Since the @error directive compiles to an "if" statement, you may use the @else directive to render content when there is not an error for an attribute:

You may pass the name of a specific error bag as the second parameter to the @error directive to retrieve validation error messages on pages containing multiple forms:

Blade allows you to push to named stacks which can be rendered somewhere else in another view or layout. This can be particularly useful for specifying any JavaScript libraries required by your child views:

If you would like to @push content if a given boolean expression evaluates to true , you may use the @pushIf directive:

You may push to a stack as many times as needed. To render the complete stack contents, pass the name of the stack to the @stack directive:

If you would like to prepend content onto the beginning of a stack, you should use the @prepend directive:

The @inject directive may be used to retrieve a service from the Laravel service container . The first argument passed to @inject is the name of the variable the service will be placed into, while the second argument is the class or interface name of the service you wish to resolve:

Sometimes you may need to transform a raw Blade template string into valid HTML. You may accomplish this using the render method provided by the Blade facade. The render method accepts the Blade template string and an optional array of data to provide to the template:

Laravel renders inline Blade templates by writing them to the storage/framework/views directory. If you would like Laravel to remove these temporary files after rendering the Blade template, you may provide the deleteCachedView argument to the method:

When using frontend frameworks such as Turbo and htmx , you may occasionally need to only return a portion of a Blade template within your HTTP response. Blade "fragments" allow you to do just that. To get started, place a portion of your Blade template within @fragment and @endfragment directives:

Then, when rendering the view that utilizes this template, you may invoke the fragment method to specify that only the specified fragment should be included in the outgoing HTTP response:

The fragmentIf method allows you to conditionally return a fragment of a view based on a given condition. Otherwise, the entire view will be returned:

The fragments and fragmentsIf methods allow you to return multiple view fragments in the response. The fragments will be concatenated together:

Extending Blade

Blade allows you to define your own custom directives using the directive method. When the Blade compiler encounters the custom directive, it will call the provided callback with the expression that the directive contains.

The following example creates a @datetime($var) directive which formats a given $var , which should be an instance of DateTime :

As you can see, we will chain the format method onto whatever expression is passed into the directive. So, in this example, the final PHP generated by this directive will be:

[!WARNING] After updating the logic of a Blade directive, you will need to delete all of the cached Blade views. The cached Blade views may be removed using the view:clear Artisan command.

If you attempt to "echo" an object using Blade, the object's __toString method will be invoked. The __toString method is one of PHP's built-in "magic methods". However, sometimes you may not have control over the __toString method of a given class, such as when the class that you are interacting with belongs to a third-party library.

In these cases, Blade allows you to register a custom echo handler for that particular type of object. To accomplish this, you should invoke Blade's stringable method. The stringable method accepts a closure. This closure should type-hint the type of object that it is responsible for rendering. Typically, the stringable method should be invoked within the boot method of your application's AppServiceProvider class:

Once your custom echo handler has been defined, you may simply echo the object in your Blade template:

Programming a custom directive is sometimes more complex than necessary when defining simple, custom conditional statements. For that reason, Blade provides a Blade::if method which allows you to quickly define custom conditional directives using closures. For example, let's define a custom conditional that checks the configured default "disk" for the application. We may do this in the boot method of our AppServiceProvider :

Once the custom conditional has been defined, you can use it within your templates:

An official website of the United States Government

  • Kreyòl ayisyen
  • Search Toggle search Search Include Historical Content - Any - No Include Historical Content - Any - No Search
  • Menu Toggle menu
  • Individuals
  • Business & Self Employed
  • Charities and Nonprofits
  • International Taxpayers
  • Federal State and Local Governments
  • Indian Tribal Governments
  • Tax Exempt Bonds
  • How to File
  • When to File
  • Where to File
  • Update Your Information
  • Get Your Tax Record
  • Apply for an Employer ID Number (EIN)
  • Check Your Amended Return Status
  • Get an Identity Protection PIN (IP PIN)
  • File Your Taxes for Free
  • Bank Account (Direct Pay)
  • Debit or Credit Card
  • Payment Plan (Installment Agreement)
  • Electronic Federal Tax Payment System (EFTPS)
  • Your Online Account
  • Tax Withholding Estimator
  • Estimated Taxes
  • Where's My Refund
  • What to Expect
  • Direct Deposit
  • Reduced Refunds
  • Amend Return

Credits & Deductions

  • Businesses & Self-Employed
  • Earned Income Credit (EITC)
  • Child Tax Credit
  • Clean Energy and Vehicle Credits
  • Standard Deduction
  • Retirement Plans

Forms & Instructions

  • Form 1040 Instructions
  • Form 4506-T
  • Form 1040-X
  • Circular 230

Credits and deductions for individuals

In this series:.

How to file your taxes: step by step Check if you need to file Gather your documents Get credits and deductions File your return Get your refund Pay taxes on time Be ready to file taxes next year

How they work

You can claim credits and deductions when you file your tax return to lower your tax. Make sure you get all the credits and deductions you qualify for.

Claim credits 

A credit is an amount you subtract from the tax you owe. This can lower your tax payment or increase your refund. Some credits are refundable  — they can give you money back even if you don't owe any tax. 

To claim credits, answer questions in your tax filing software. If you file a paper return, you’ll need to complete a form and attach it. 

Here are credits you can claim: 

If you earn under a certain income level .

See if you qualify for the Earned Income Tax Credit . This is a refundable credit, so you can get back more than you pay in taxes. If you qualify, you can claim it even if you don’t normally file taxes or aren’t required to file. 

If you’re a parent or caretaker

Find credits if you: 

Have children or other dependents  

Adopt a child  

Pay for childcare or dependent care  

If you pay for higher education

See if you qualify for an education credit

If you put money into retirement savings

See if you qualify for the saver’s credit  

If you invest in clean vehicles or clean home energy

Buy a clean (electric or hybrid) vehicle  

Make home energy improvements  

If you buy health insurance in the marketplace

See if you qualify for the Premium Tax Credit

If you qualify for other personal tax credits

Find less common credits for people who: 

Paid taxes overseas  

Overpaid Social Security or RRTA tax  

Paid alternative minimum tax in prior years  

Paid tax on undistributed capital gains  

Take deductions 

A deduction is an amount you subtract from your income when you file so you don’t pay tax on it. By lowering your income, deductions lower your tax. 

You need documents to show expenses or losses you want to deduct. Your tax software will calculate deductions for you and enter them in the right forms. If you file a paper return, your deductions go on Form 1040 and may require extra forms. 

Standard vs. itemized deductions 

Most people take the standard deduction, which lets you subtract a set amount from your income based on your filing status . 

If your deductible expenses and losses are more than the standard deduction, you can save money by deducting them one-by-one from your income (itemizing). Tax software can walk you through your expenses and losses to show the option that gives you the lowest tax. 

Some people, including nonresidents and partial-year filers, can’t take the standard deduction . 

Standard deduction amounts 

The standard deduction for 2023 is: 

$13,850 for single or married filing separately 

$27,700 for married couples filing jointly or qualifying surviving spouse 

$20,800 for head of household 

Find the standard deduction if you’re: 

  • Over 65 or blind
  • A dependent on someone else’s tax return

If you’re married filing separately, you can’t take the standard deduction if your spouse itemizes. You must both choose the same method.  

Deductible expenses 

You can deduct these expenses whether you take the standard deduction or itemize:

  • Alimony payments  
  • Business use of your car  
  • Business use of your home  
  • Money you put in an IRA  
  • Money you put in health savings accounts  
  • Penalties on early withdrawals from savings  
  • Student loan interest  
  • Teacher expenses  
  • For some military, government, self-employed and people with disabilities: work-related education expenses  
  • For military servicemembers: moving expenses  

If you itemize, you can deduct these expenses:

  • Bad debts  
  • Canceled debt on home  
  • Capital losses  
  • Donations to charity  
  • Gains from sale of your home  
  • Gambling losses  
  • Home mortgage interest  
  • Income, sales, real estate and personal property taxes  
  • Losses from disasters and theft  
  • Medical and dental expenses over 7.5% of your adjusted gross income  
  • Miscellaneous itemized deductions  
  • Opportunity zone investment  

Get answers to questions on itemized deductions and the standard deduction

  Previous Gather your documents

Next   File your return

  •  Facebook
  •  Twitter
  •  Linkedin

Choosing a Runtime

Vercel supports multiple runtimes for your functions. Each runtime has its own set of libraries, APIs, and functionality that provides different trade-offs and benefits.

Runtimes transform your source code into Functions , which are served by our Edge Network .

Runtime configuration is usually only necessary when you want to use the Edge runtime.

Vercel supports these official runtimes:

Community runtimes

If you would like to use a language that Vercel does not support by default, you can use a community runtime by setting the functions property in vercel.json . For more information on configuring other runtimes, see Configuring your function runtime .

The following community runtimes are recommended by Vercel:

You can create a community runtime by using the Runtime API . Alternatively, you can use the Build Output API .

Caching Data

A runtime can retain an archive of up to 100 MB of the filesystem at build time. The cache key is generated as a combination of:

  • Project name
  • Team ID or User ID
  • Entrypoint path (e.g., api/users/index.go )
  • Runtime identifier including version (e.g.: @vercel/[email protected] )

The cache will be invalidated if any of those items changes. You can bypass the cache by running vercel -f .

Runtimes comparison

When using functions on Vercel, you can choose what runtime you want to use:

  • Node.js (Serverless)
  • Go, Python, Ruby - These runtimes are available in Beta for use with Serverless Functions .

Usually, when writing TypeScript or JavaScript functions, you'll be deciding between the Node.js or Edge runtime. The following sections provide information on the trade-offs and benefits of each.

Node.js -powered functions are suited to computationally intense or large functions and provide benefits like:

  • More RAM and CPU power – For computationally intense workloads, or functions that have bundles up to 250 MB in size, this runtime is ideal
  • Complete Node.js compatibility - The Node.js runtime offers access to all Node.js APIs, making it a powerful tool for many applications, although it may take them longer to boot than those using the Edge runtime

In our documentation and this guide, we mention Serverless Functions . These are Node.js -powered Vercel Functions. To learn how to implement these functions, see the quickstart .

Edge runtime -powered functions can be a cost-effective option and provide benefits like:

  • Lightweight with a slim runtime - With a smaller API surface area and using V8 isolates, Edge runtime-powered functions have a slim runtime. However, only a subset of Node.js APIs are exposed
  • Globally distributed by default – Vercel deploys all Edge Functions globally across its Edge Network, which means your site's visitors will get API responses from data centers geographically near them, typically reducing the overall response time
  • Pricing is based on compute time – You're charged for time processing any requests and not for your function is fetching data. This is ideal for querying databases or AI services that may have longer request times

Responses from Edge Functions can be cached and streamed in real time.

In our documentation and this guide, we mention Edge Functions . These are Edge runtime -powered Vercel Functions. To learn how to implement these functions, see the quickstart .


Runtime is the environment in which your functions execute. Vercel supports several runtimes for Serverless Functions ( Node.js , Go , Ruby , Python ), while Edge Functions use the lightweight Edge runtime.

This means that with Serverless Functions you have access to all Node.js APIs. With Edge Functions you get access to a subset of the most important browser APIs.

Cold starts

Cold starts refer to the delay that occurs when an inactive Function is invoked for the first time, as the function has to be initialized and loaded into memory.

When a function uses the lightweight Edge runtime , it needs fewer resources to initialize and therefore can have faster cold starts than Node.js-powered functions.

Location refers to where your functions are executed . Serverless Functions are region-first, while Edge Functions are executed close to the end-users across Vercel's global network.

When you deploy Edge Functions, there are considerations you need to make about where it's deployed and executes. Edge Functions are executed globally and in a region close to the user's request. However, if your data source is geographically far from this request, any response will be slow. Because of this you can opt to execute your function closer to your data source .

Users on Enterprise plans can deploy Serverless Functions to multiple regions. On non-Enterprise plans, deploying to multiple regions will fail before entering the build step . Users on any plan can deploy Edge Functions to multiple regions.

Failover mode

Vercel's failover mode refers to the system's behavior when a function fails to execute because of data center downtime.

Vercel provides redundancy and automatic failover for Edge Functions to ensure high availability. For Serverless Functions, you can use the functionFailoverRegions configuration in your vercel.json file to specify which regions the function should automatically failover to.

Automatic concurrency scaling

The concurrency model on Vercel refers to how many instances of your functions can run simultaneously. All functions on Vercel scale automatically based on demand to manage increased traffic loads.

With automatic concurrency scaling, your Vercel Functions can scale to a maximum of 30,000 , maintaining optimal performance during traffic surges. The scaling is based on the burst concurrency limit of 1000 concurrent executions per 10 seconds , per region.

Vercel's infrastructure monitors your usage and preemptively adjusts the concurrency limit to cater to growing traffic, allowing your applications to scale without your intervention.

Automatic concurrency scaling is available on all plans .

Burst concurrency limits

Burst concurrency refers to Vercel's ability to temporarily handle a sudden influx of traffic by allowing a higher concurrency limit.

Upon detecting a traffic spike, Vercel temporarily increases the concurrency limit to accommodate the additional load. The initial increase allows for a maximum of 1000 concurrent executions per 10 seconds , scaling up to a total of 30,000 concurrent executions , if necessary. After the traffic burst subsides, the concurrency limit gradually returns to its previous state, ensuring a smooth scaling experience.

The scaling process may take several minutes during traffic surges, especially substantial ones. While this delay aligns with natural traffic curves to minimize potential impact on your application's performance, it's advisable to monitor the scaling process for optimal operation.

You can monitor burst concurrency events using Log Drains , or Runtime Logs to help you understand and optimize your application's performance.

If you exceed the 30,000 limit, a 429 FUNCTION_RATE_LIMIT error will trigger. Alternatively, you can explore Edge Functions , which do not have concurrency limits.

Isolation boundary

In Vercel, the isolation boundary refers to the separation of individual instances of a function to ensure they don't interfere with each other. This provides a secure execution environment for each function.

With traditional serverless infrastructure, each function uses a lightweight virtual machine for isolation, which provides strong security but also makes them slower to start and more resource intensive. As the Edge runtime is built on the V8 engine , it uses V8 isolates to separate just the runtime context, allowing for quick startup times and high performance.

File system support

Filesystem support refers to a function's ability to read and write to the filesystem. Serverless Functions have a read-only filesystem with writable /tmp scratch space up to 500 MB. Edge Functions do not have filesystem access due to their ephemeral nature.

Serverless Functions are archived when they are not invoked:

  • Within 2 weeks for Production Deployments
  • Within 48 hours for Preview Deployments

Archived functions will be unarchived when they're invoked, which can make the initial cold start time at least 1 second longer than usual.

Edge Functions are not archived.

Functions created per deployment

When using Next.js or SvelteKit on Vercel, dynamic code (APIs, server-rendered pages, or dynamic fetch requests) will be bundled into the fewest number of Serverless Functions possible, to help reduce cold starts. Because of this, it's unlikely that you'll hit the limit of 12 bundled Serverless Functions per deployment.

When using other frameworks , or Serverless Functions directly without a framework , every API maps directly to one Serverless Function. For example, having five files inside api/ would create five Serverless Functions. For Hobby, this approach is limited to 12 Serverless Functions per deployment.

Size limits

Bundle size limits.

Vercel places restrictions on the maximum size of the deployment bundle for functions to ensure that they execute in a timely manner.

For Serverless Functions, the maximum uncompressed size is 250 MB including layers which are automatically used depending on runtimes . These limits are enforced by AWS .

You can use includeFiles and excludeFiles to specify items which may affect the function size, however the limits cannot be configured. These configurations are not supported in Next.js, instead use outputFileTracingIncludes . å Edge Functions have plan-dependent size limits. This is the total, compressed size of your function and its dependencies after bundling.

Max duration

This refers to the longest time a function can process an HTTP request before responding.

Functions using the Edge runtime do not have a maximum duration. They must begin sending a response within 25 seconds and can continue streaming a response beyond that time.

While Serverless Functions have a default duration, this duration can be extended using the maxDuration config . If a Serverless Function doesn't respond within the duration, a 504 error code ( FUNCTION_INVOCATION_TIMEOUT ) is returned.

Serverless Functions have the following defaults and maximum limits for the duration of a function:

Memory size limits

Serverless Functions can use more memory and larger CPUs than Edge Functions. The maximum memory for a Serverless Function is 1024 MB on a Hobby plan, and up to 3008 MB on Pro and Enterprise plans, by using the functions property in your vercel.json .

Edge Functions have a fixed memory limit, ensuring minimal cold starts in a limited execution environment. When you exceeds this limit, the execution will be aborted and we will return a 502 error.

The maximum size for a Function includes your JavaScript code, imported libraries and files (such as fonts), and all files bundled in the function.

If you reach the limit, make sure the code you are importing in your function is used and is not too heavy. You can use a package size checker tool like bundle to check the size of a package and search for a smaller alternative.

Environment variables

You can use environment variables to manage dynamic values and sensitive information affecting the operation of your functions. Vercel allows developers to define these variables either at deployment or during runtime.

You can use a total of 64 KB in environments variables per-deployment on Vercel. This limit is for all variables combined, and so no single variable can be larger than 64 KB .

Request body size

In Vercel, the request body size is the maximum amount of data that can be included in the body of a request to a function. Edge Functions also have additional limits to the request size:

The maximum payload size for the request body or the response body of a Serverless Function is 4.5 MB . If a Serverless Function receives a payload in excess of the limit it will return an error 413: FUNCTION_PAYLOAD_TOO_LARGE . See How do I bypass the 4.5MB body size limit of Vercel Serverless Functions for more information.

API support

You can learn more about API support and writing functions:

  • Serverless Functions: Node.js runtime
  • Edge Functions: Edge Functions API

Edge Function API support

Edge Functions are neither Node.js nor browser applications, which means they don't have access to all browser and Node.js APIs. Currently, the Edge runtime offers a subset of browser APIs and some Node.js APIs .

There are some restrictions when writing Edge Functions:

  • Use ES modules
  • Most libraries which use Node.js APIs as dependencies can't be used in Edge Functions yet. See available APIs for a full list

Limits on fetch API

  • You cannot set non-standard port numbers in the fetch URL (e.g., ). Only 80 and 443 are allowed. If you set a non-standard port number, the port number is ignored, and the request is sent to port 80 for http:// URL, or port 443 for https:// URL.
  • The maximum number of requests from fetch API is 950 per Edge Function invocation.
  • Each function invocation can have up to 6 open connections. For example, if you try to send 10 simultaneous fetch requests, only 6 of them can be processed at a time. The remaining requests are put into a waiting queue and will be processed accordingly as those in-flight requests are completed.

Limited Date API

To avoid CPU timing attacks, like Spectre, date and time functionality is not generally available. In particular, the time returned from only advances after I/O operations, like fetch . For example:

Cost and usage

Billing model.

The Hobby plan offers functions for free, within limits . The Pro plan extends these limits, billing Serverless Functions on wall-clock time and Edge runtime-powered Functions on CPU time .

This aligns with the intended usage of each: Serverless for intermittent heavy tasks, and Edge for continuous low-latency tasks. The Edge runtime is particularly well-suited for querying databases or other backends, like an AI service, since you will not be billed for the time making the request, only the time processing the response.

See Usage and Pricing for more information.

Edge Middleware CPU Limit

Edge Middleware can use no more than 50 ms of CPU time on average.

This limitation refers to actual net CPU time, which is the time spent performing calculations, not the total elapsed execution or "wall clock" time. For example, when you are blocked talking to the network, the time spent waiting for a response does not count toward CPU time limitations.

Feature support

Secure compute.

Vercel's Secure Compute feature offers enhanced security for your Serverless Functions, including dedicated IP addresses and VPN options. This can be particularly important for functions that handle sensitive data.

Streaming refers to the ability to send or receive data in a continuous flow.

Both the Node.js and the Edge runtime support streaming.

In addition, Serverless Functions have a maximum duration , meaning that it isn't possible to stream indefinitely. Edge Functions do not have a maximum duration, but you must send an initial response within 25 seconds. You can continue streaming a response beyond that time.

Cron jobs are time-based scheduling tools used to automate repetitive tasks. When a cron job is triggered through the cron expression , it calls a Vercel Function.

Vercel Storage

From your function, you can communicate with a choice of data stores . To ensure low-latency responses, it's crucial to have compute close to your databases. Always deploy your databases in regions closest to your functions to avoid long network roundtrips. For more information, see our best practices documentation.

Edge Config

An Edge Config is a global data store that enables experimentation with feature flags, A/B testing, critical redirects, and IP blocking. It enables you to read data at the edge without querying an external database or hitting upstream servers.

Vercel has an OpenTelemetry (OTEL) collector that allows you to send OTEL traces from your Serverless Functions to application performance monitoring (APM) vendors such as New Relic.

Was this helpful?

Connectivity  >  Protocols  >  Stomp

ActiveMQ Classic supports the Stomp protocol and the Stomp - JMS mapping. This makes it easy to write a client in pure Ruby , Perl , Python or PHP for working with ActiveMQ Classic.

Please see the Stomp site for more details

Spec Compliance

ActiveMQ Classic v5.6 implements the Stomp v1.1 spec except for allowing spaces at the beginning or end of message header keys, they are preserved in the header values however. In future releases this will not be the case, clients should be updated and user code checked to ensure that spaces in the headers are there intentionally and not as a accident or a client “feature”.

Enabling the ActiveMQ Classic Broker for Stomp

To enable STOMP protocol support in the broker add a transport connector definition whose URI scheme is stomp .

To see a full example, try this XML . If you save that XML as  foo.xml then you can run stomp via the command line as

For more help see Run Broker .

The Stomp Wire Format

Stomp uses a text based wire format that can be configured with the following options.  All options can be configured on a Brokers transport bind URI.

Use the Correct Prefix! Wire format options must have the prefix  wireFormat. to take effect, e.g.,  wireFormat.`maxDataLength`=100000 . Options missing this prefix will be ignored.

From ActiveMQ Classic 5.1 : Stomp fully supports ActiveMQ Classic’s security mechanism. This means that the CONNECT command will return an ERROR STOMP frame on unsuccessful authentication. Also, the authorization policies will be applied when you try to access (read/write) certain destinations. If you use synchronous operations (by using receipts ), you can expect an ERROR frame in case of unauthorized access attempt. In other case, operations will be discarded but the client will not be informed of errors. This applies to all errors that can occur broker-side.

SSL For additional security, you can use Stomp over SSL as described in the following section.

Enabling Stomp over NIO

From ActiveMQ Classic 5.3 : for better scalability and performance the Stomp protocol can be configured to be run over the NIO transport. The NIO transport will use far fewer threads than the corresponding TCP connector. This can help when support for a large number of queues is required. To use NIO change the URI scheme of the transport connector to stomp+nio .

Enabling Stomp over SSL

To configure ActiveMQ Classic to use Stomp over an SSL connection change the URI scheme to stomp+ssl .

For more details on using SSL with ActiveMQ Classic see the following article ( How do I use SSL ). An example of using Stomp over SSL on the client side can be found in the PHP Stomp client example .

Heart-Beat Grace Period

The STOMP protocol (version 1.1 or greater) defines the concept of heart beats as a method by which a client and broker can determine the health of the underlying TCP connection between them. ActiveMQ Classic supports STOMP heart beating provided the client is using version 1.1 (or greater) of the protocol.

Before ActiveMQ Classic 5.9.0 : enforcement of the ‘read’ heart-beat timeout (that is, a heart-beat sent from the client to the broker) was strict. In other words, the broker was intolerant of late arriving read heart-beats from the client. This resulted in the broker concluding that the client was no longer present causing it to close its side of the client’s connection when the client failed to honor it’s configured heart-beat settings.

From ActiveMQ Classic 5.9.0 : the timeout enforcement for read heart-beats is now configurable via a new transport option  transport.hbGracePeriodMultiplier :

This multiplier is used to calculate the effective read heart-beat timeout the broker will enforce for each client’s connection. The multiplier is applied to the read-timeout interval the client specifies in its  CONNECT frame:

For backward compatibility, if the grace period multiplier is not configured the default enforcement mode remains strict, e.g.,  transport.hbGracePeriodMultiplier=1.0 . Attempts to configure the grace period multiplier to a value less than, or equal to  1.0 will be silently ignored.

STOMP clients that wish to be tolerant of late arriving heart-beats from the broker must implement their own solution for doing so.

Please check the STOMP specification for the details on heart-beating

The JIRA that implemented this: ActiveMQ Classic 5.x does not support the notion of a grace-period for heart beats as supported by the STOMP protocol

Working with Destinations with Stomp

Note that the prefix in stomp /queue/ or  /topic/ is removed from the string before passing it to ActiveMQ Classic as a JMS destination. Also note that the default separator in MOM systems is  . (dot). Whilst FOO.BAR is the normal syntax to identify a queue type destination the Stomp equivalent is /queue/FOO.BAR

Be careful about starting destinations with / If in Stomp world you use  /queue/foo/bar then in a JMS world the queue would be called foo/bar not  /foo/bar .
Persistent Messaging in STOMP STOMP messages are non-persistent by default. To use persistent messaging add the following STOMP header to all  SEND requests: persistent:true . This default is the opposite of that for JMS messages.

Working with JMS Text/Bytes Messages and Stomp

Stomp is a very simple protocol - that’s part of the beauty of it! As such, it does not have knowledge of JMS messages such as  TextMessage ’s or BytesMessage ’s. The protocol does however support a  content-length header. To provide more robust interaction between STOMP and JMS clients, ActiveMQ Classic keys off of the inclusion of this header to determine what message type to create when sending from Stomp to JMS. The logic is simple:

This same logic can be followed when going from JMS to Stomp, as well. A Stomp client could be written to key off of the inclusion of the  content-length header to determine what type of message structure to provide to the user.

Message Transformations

The transformation message header on SEND and SUBSCRIBE messages could be used to instruct ActiveMQ Classic to transform messages from text to the format of your desire. Currently, ActiveMQ Classic comes with a transformer that can transform XML/JSON text to Java objects, but you can add your own transformers as well.

Here’s a quick example of how to use built-in transformer (taken from test cases)

Dependencies ActiveMQ Classic uses XStream for its transformation needs. Since it’s the optional dependency you have to add it to broker’s classpath by putting the appropriate JAR into the lib/ folder. Additionally, if you plan to use JSON transformations you have to add Jettison JSON parser to the classpath.

In order to create your own transformer, you have to do the following:

Build your transformer by implementing a FrameTranslator interface

Associate it with the appropriate header value by creating a file named as a value you want to use in the META-INF/services/org/apache/activemq/transport/frametranslator/ folder of your JAR which will contain the value class=_fully qualified classname of your transformer_

For example the built-in transformer contains the following value:

in the META-INF/services/org/apache/activemq/transport/frametranslator/jms-xml file.

In case you want to debug Stomp communication between broker and clients you should configure the Stomp connector with the trace parameter, like this:

This will instruct the broker to trace all packets it sends and receives.

Furthermore, you have to enable tracing for the appropriate log. You can achieve that by adding the following to your conf/

Finally, you will probably want to keep these messages in the separate file instead of polluting the standard broker’s log. You can achieve that with the following log4j configuration:

After this, all your Stomp packets will be logged to the data/stomp.log

From ActiveMQ Classic 5.2 : there is a simple Java Stomp API distributed with ActiveMQ Classic. Note that this API is provided purely for testing purposes and you should always consider using standard JMS API from Java instead of this one. The following code snippet provides a simple example of using this API:

This example is part of the standard ActiveMQ Classic distribution. You can run it from the  ./example folder with:

Stomp Extensions for JMS Message Semantics

Note that STOMP is designed to be as simple as possible - so any scripting language/platform can message any other with minimal effort. STOMP allows pluggable headers on each request such as sending & receiving messages. ActiveMQ Classic has several extensions to the Stomp protocol, so that JMS semantics can be supported by Stomp clients. An OpenWire JMS producer can send messages to a Stomp consumer, and a Stomp producer can send messages to an OpenWire JMS consumer. And Stomp to Stomp configurations, can use the richer JMS message control.

STOMP supports the following standard JMS properties on  SENT messages:

ActiveMQ Classic Extensions to STOMP

You can add custom headers to STOMP commands to configure the ActiveMQ Classic protocol. Here are some examples:

how to write php documentation

Apache, ActiveMQ, Apache ActiveMQ , the Apache feather logo, and the Apache ActiveMQ project logo are trademarks of The Apache Software Foundation. Copyright © 2024, The Apache Software Foundation. Licensed under Apache License 2.0 .

how to write php documentation

'ZDNET Recommends': What exactly does it mean?

ZDNET's recommendations are based on many hours of testing, research, and comparison shopping. We gather data from the best available sources, including vendor and retailer listings as well as other relevant and independent reviews sites. And we pore over customer reviews to find out what matters to real people who already own and use the products and services we’re assessing.

When you click through from our site to a retailer and buy a product or service, we may earn affiliate commissions. This helps support our work, but does not affect what we cover or how, and it does not affect the price you pay. Neither ZDNET nor the author are compensated for these independent reviews. Indeed, we follow strict guidelines that ensure our editorial content is never influenced by advertisers.

ZDNET's editorial team writes on behalf of you, our reader. Our goal is to deliver the most accurate information and the most knowledgeable advice possible in order to help you make smarter buying decisions on tech gear and a wide array of products and services. Our editors thoroughly review and fact-check every article to ensure that our content meets the highest standards. If we have made an error or published misleading information, we will correct or clarify the article. If you see inaccuracies in our content, please report the mistake via this form .

How to use Copilot Pro to write, edit, and analyze your Word documents


Microsoft's Copilot Pro AI offers a few benefits for $20 per month. But the most helpful one is the AI-powered integration with the different Microsoft 365 apps. For those of you who use Microsoft Word, for instance, Copilot Pro can help you write and revise your text, provide summaries of your documents, and answer questions about any document.

First, you'll need a subscription to either Microsoft 365 Personal or Family . Priced at $70 per year, the Personal edition is geared for one individual signed into as many as five devices. At $100 per year, the Family edition is aimed at up to six people on as many as five devices. The core apps in the suite include Word, Excel, PowerPoint, Outlook, and OneNote.

Also: Microsoft Copilot vs. Copilot Pro: Is the subscription fee worth it?

Second, you'll need the subscription to Copilot Pro if you don't already have one. To sign up, head to the Copilot Pro website . Click the Get Copilot Pro button. Confirm the subscription and the payment. The next time you use Copilot on the website, in Windows, or with the mobile apps, the Pro version will be in effect.

How to use Copilot Pro in Word

1. open word.

Launch Microsoft Word and open a blank document. Let's say you need help writing a particular type of document and want Copilot to create a draft. 

Also: Microsoft Copilot Pro vs. OpenAI's ChatGPT Plus: Which is worth your $20 a month?

A small "Draft with Copilot" window appears on the screen. If you don't see it, click the tiny "Draft with Copilot icon in the left margin."


2. Submit your request

At the text field in the window, type a description of the text you need and click the "Generate" button.


Submit your request.

3. Review the response and your options

Copilot generates and displays its response. After reading the response, you're presented with a few different options.


Review the response and your options.

4. Keep, regenerate, or remove the draft

If you like the draft, click "Keep it." The draft is then inserted into your document where you can work with it. If you don't like the draft, click the "Regenerate" button, and a new draft is created. 

Also: What is Copilot (formerly Bing Chat)? Here's everything you need to know

If you'd prefer to throw out the entire draft and start from scratch, click the trash can icon.


Keep, regenerate, or remove the draft.

5. Alter the draft

Alternatively, you can try to modify the draft by typing a specific request in the text field, such as "Make it more formal," "Make it shorter," or "Make it more casual."


Alter the draft.

6. Review the different versions

If you opt to regenerate the draft, you can switch between the different versions by clicking the left or right arrow next to the number. You can then choose to keep the draft you prefer.


7. Revise existing text

Copilot will also help you fine-tune existing text. Select the text you want to revise. Click the Copilot icon in the left margin and select "Rewrite with Copilot."


Revise existing text.

8. Review the different versions

Copilot creates a few different versions of the text. Click the arrow keys to view each version.


Review the different versions.

9. Replace or Insert

If you find one you like, click "Replace" to replace the text you selected. 

Also: ChatGPT vs. Microsoft Copilot vs. Gemini: Which is the best AI chatbot?

Click "Insert below" to insert the new draft below the existing words so you can compare the two.


Replace or Insert.

10. Adjust the tone

Click "Regenerate" to ask Copilot to try again. Click the "Adjust Tone" button and select a different tone to generate another draft.


Adjust the tone.

11. Turn text into a table

Sometimes you have text that would look and work better as a table. Copilot can help. Select the text you wish to turn into a table. Click the Copilot icon and select "Visualize as a Table."


Turn text into a table.

12. Respond to the table

In response, click "Keep it" to retain the table. Click "Regenerate" to try again. Click the trash can icon to delete it. Otherwise, type a request in the text field, such as "remove the second row" or "make the last column wider."


Respond to the table.

13. Summarize a document

Copilot Pro can provide a summary of a document with its key points. To try this, open the document you want to summarize and then click the Copilot icon on the Ribbon. 

Also: The best AI chatbots

The right sidebar displays several prompts you can use to start your question. Click the one for "Summarize this doc."


Summarize a document.

14. Review the summary

View the generated summary in the sidebar. If you like it as is, click the "Copy" button to copy the summary and paste it elsewhere.


Review the summary.

15. Revise the summary

Otherwise, choose one of the suggested questions or ask your own question to revise the summary. For example, you could tell Copilot to make the summary longer, shorter, more formal, or less formal. 

Also: The best AI image generators

You could also ask it to expand on one of the points in the summary or provide more details on a certain point. A specific response is then generated based on your request.


Revise the summary.

16. Ask questions about a document

Next, you can ask specific questions about any of the content in a document. Again, click the Copilot icon to display the sidebar. In the prompt area, type and submit your question. Copilot displays the response in the sidebar. You can then ask follow-up questions as needed.


Ask questions about a document.

More how-tos


Microsoft to add Copilot AI to OneDrive, but it will cost you


Microsoft expands Copilot data protection so more users can chat with ease


Get Microsoft Office Professional for Mac or PC for $60 with this deal: Last chance

how to write php documentation

Create a form in Word that users can complete or print

In Word, you can create a form that others can fill out and save or print.  To do this, you will start with baseline content in a document, potentially via a form template.  Then you can add content controls for elements such as check boxes, text boxes, date pickers, and drop-down lists. Optionally, these content controls can be linked to database information.  Following are the recommended action steps in sequence.  

Show the Developer tab

In Word, be sure you have the Developer tab displayed in the ribbon.  (See how here:  Show the developer tab .)

Open a template or a blank document on which to base the form

You can start with a template or just start from scratch with a blank document.

Start with a form template

Go to File > New .

In the  Search for online templates  field, type  Forms or the kind of form you want. Then press Enter .

In the displayed results, right-click any item, then select  Create. 

Start with a blank document 

Select Blank document .

Add content to the form

Go to the  Developer  tab Controls section where you can choose controls to add to your document or form. Hover over any icon therein to see what control type it represents. The various control types are described below. You can set properties on a control once it has been inserted.

To delete a content control, right-click it, then select Remove content control  in the pop-up menu. 

Note:  You can print a form that was created via content controls. However, the boxes around the content controls will not print.

Insert a text control

The rich text content control enables users to format text (e.g., bold, italic) and type multiple paragraphs. To limit these capabilities, use the plain text content control . 

Click or tap where you want to insert the control.

Rich text control button

To learn about setting specific properties on these controls, see Set or change properties for content controls .

Insert a picture control

A picture control is most often used for templates, but you can also add a picture control to a form.

Picture control button

Insert a building block control

Use a building block control  when you want users to choose a specific block of text. These are helpful when you need to add different boilerplate text depending on the document's specific purpose. You can create rich text content controls for each version of the boilerplate text, and then use a building block control as the container for the rich text content controls.

building block gallery control

Select Developer and content controls for the building block.

Developer tab showing content controls

Insert a combo box or a drop-down list

In a combo box, users can select from a list of choices that you provide or they can type in their own information. In a drop-down list, users can only select from the list of choices.

combo box button

Select the content control, and then select Properties .

To create a list of choices, select Add under Drop-Down List Properties .

Type a choice in Display Name , such as Yes , No , or Maybe .

Repeat this step until all of the choices are in the drop-down list.

Fill in any other properties that you want.

Note:  If you select the Contents cannot be edited check box, users won’t be able to click a choice.

Insert a date picker

Click or tap where you want to insert the date picker control.

Date picker button

Insert a check box

Click or tap where you want to insert the check box control.

Check box button

Use the legacy form controls

Legacy form controls are for compatibility with older versions of Word and consist of legacy form and Active X controls.

Click or tap where you want to insert a legacy control.

Legacy control button

Select the Legacy Form control or Active X Control that you want to include.

Set or change properties for content controls

Each content control has properties that you can set or change. For example, the Date Picker control offers options for the format you want to use to display the date.

Select the content control that you want to change.

Go to Developer > Properties .

Controls Properties  button

Change the properties that you want.

Add protection to a form

If you want to limit how much others can edit or format a form, use the Restrict Editing command:

Open the form that you want to lock or protect.

Select Developer > Restrict Editing .

Restrict editing button

After selecting restrictions, select Yes, Start Enforcing Protection .

Restrict editing panel

Advanced Tip:

If you want to protect only parts of the document, separate the document into sections and only protect the sections you want.

To do this, choose Select Sections in the Restrict Editing panel. For more info on sections, see Insert a section break .

Sections selector on Resrict sections panel

If the developer tab isn't displayed in the ribbon, see Show the Developer tab .

Open a template or use a blank document

To create a form in Word that others can fill out, start with a template or document and add content controls. Content controls include things like check boxes, text boxes, and drop-down lists. If you’re familiar with databases, these content controls can even be linked to data.

Go to File > New from Template .

New from template option

In Search, type form .

Double-click the template you want to use.

Select File > Save As , and pick a location to save the form.

In Save As , type a file name and then select Save .

Start with a blank document

Go to File > New Document .

New document option

Go to File > Save As .

Go to Developer , and then choose the controls that you want to add to the document or form. To remove a content control, select the control and press Delete. You can set Options on controls once inserted. From Options, you can add entry and exit macros to run when users interact with the controls, as well as list items for combo boxes, .

Adding content controls to your form

In the document, click or tap where you want to add a content control.

On Developer , select Text Box , Check Box , or Combo Box .

Developer tab with content controls

To set specific properties for the control, select Options , and set .

Repeat steps 1 through 3 for each control that you want to add.

Set options

Options let you set common settings, as well as control specific settings. Select a control and then select Options to set up or make changes.

Set common properties.

Select Macro to Run on lets you choose a recorded or custom macro to run on Entry or Exit from the field.

Bookmark Set a unique name or bookmark for each control.

Calculate on exit This forces Word to run or refresh any calculations, such as total price when the user exits the field.

Add Help Text Give hints or instructions for each field.

OK Saves settings and exits the panel.

Cancel Forgets changes and exits the panel.

Set specific properties for a Text box

Type Select form Regular text, Number, Date, Current Date, Current Time, or Calculation.

Default text sets optional instructional text that's displayed in the text box before the user types in the field. Set Text box enabled to allow the user to enter text into the field.

Maximum length sets the length of text that a user can enter. The default is Unlimited .

Text format can set whether text automatically formats to Uppercase , Lowercase , First capital, or Title case .

Text box enabled Lets the user enter text into a field. If there is default text, user text replaces it.

Set specific properties for a Check box .

Default Value Choose between Not checked or checked as default.

Checkbox size Set a size Exactly or Auto to change size as needed.

Check box enabled Lets the user check or clear the text box.

Set specific properties for a Combo box

Drop-down item Type in strings for the list box items. Press + or Enter to add an item to the list.

Items in drop-down list Shows your current list. Select an item and use the up or down arrows to change the order, Press - to remove a selected item.

Drop-down enabled Lets the user open the combo box and make selections.

Protect the form

Go to Developer > Protect Form .

Protect form button on the Developer tab

Note:  To unprotect the form and continue editing, select Protect Form again.

Save and close the form.

Test the form (optional)

If you want, you can test the form before you distribute it.

Protect the form.

Reopen the form, fill it out as the user would, and then save a copy.

Creating fillable forms isn’t available in Word for the web.

You can create the form with the desktop version of Word with the instructions in Create a fillable form .

When you save the document and reopen it in Word for the web, you’ll see the changes you made.


Need more help?

Want more options.

Explore subscription benefits, browse training courses, learn how to secure your device, and more.

how to write php documentation

Microsoft 365 subscription benefits

how to write php documentation

Microsoft 365 training

how to write php documentation

Microsoft security

how to write php documentation

Accessibility center

Communities help you ask and answer questions, give feedback, and hear from experts with rich knowledge.

how to write php documentation

Ask the Microsoft Community

how to write php documentation

Microsoft Tech Community

how to write php documentation

Windows Insiders

Microsoft 365 Insiders

Was this information helpful?

Thank you for your feedback.


  1. How to create effective PHP project documentation with Read the Docs

    how to write php documentation

  2. How to create effective PHP project documentation with Read the Docs

    how to write php documentation

  3. How to Read PHP Documentation, Reading PHP Documentation, How to Learn

    how to write php documentation

  4. How to Write PHP [For Beginners]

    how to write php documentation

  5. 23: How to Include Documents in PHP

    how to write php documentation

  6. How to create effective PHP project documentation with Read the Docs

    how to write php documentation


  1. PHP structure

  2. php Lesson 01

  3. PHP Code Documentation

  4. 1

  5. PHP File_put_contents & File_get_contents Tutorial in Hindi / Urdu

  6. what to write in your journal


  1. How do you document your PHP functions and classes inline?

    /** * This is the description for the class below. * * @package my-package * @subpackage my-subpackage * @author my-name * @version my-version * ... */ class orderActions { ... What is the best and most widely-accepted form of inline documentation?

  2. PHP Tutorial

    Exercise: Insert the missing part of the code below to output "Hello World". "Hello World"; Submit Answer » Start the Exercise PHP Examples Learn by examples! This tutorial supplements all explanations with clarifying examples. See All PHP Examples PHP Quiz Test Learn by taking a quiz!

  3. PHP Documentation Standards

    PHP documentation in WordPress mostly takes the form of either formatted blocks of documentation or inline comments. The following is a list of what should be documented in WordPress files: Functions and class methods Classes Class members (including properties and constants) Requires and includes Hooks (actions and filters) Inline comments

  4. Keeping Your PHP Code Well Documented

    1. Write code that explains itself First and foremost, the code you write may serve as a good piece of documentation even without adding a single comment block to it. While transforming the...

  5. PHP: Documentation

    PHP-GTK related documentation is hosted on the PHP-GTK website. Documentation of PEAR and the various packages can be found on a separate server. You can still read a copy of the original PHP/FI 2.0 Manual on our site, which we only host for historical purposes. The same applies to the PHP 3 Manual . The PHP 4 and PHP 5 documentation has been ...

  6. Your First Set of Documentation

    The basic usage of phpDocumentor is to provide an input location using the command line options ( -d for a directory, -f for a file) and tell it to output your documentation to a folder of your liking ( -t ). For example: $ phpdoc -d ./src -t ./docs/api. What the above example does is scan all files in the src directory and its subdirectories ...

  7. PHP: A simple tutorial

    What do I need? Your first PHP-enabled page Something Useful Dealing with Forms What's next? Here we would like to show the very basics of PHP in a short, simple tutorial. This text only deals with dynamic web page creation with PHP, though PHP is not only capable of creating web pages.

  8. How to Document PHP and MySQL Project

    1. Use phpdoc syntax to document code This syntax is widely supported by many IDE's and tools - the only possible solution. In some cases you could use libraries which have defined custom tags (e.g. using Swagger about which I previously wrote an article ).

  9. PHPDocs Basics

    PHPDocs Basics. PHPDocs are a big part of what makes PHPStan work. PHP in its most recent versions can express a lot of things in the native typehints, but it still leaves a lot of room for PHPDocs to augment the information. Valid PHPDocs start with /**. Variants starting only with /* or line comments // are not considered PHPDocs.

  10. Introduction to PhpDoc

    Read Introduction to PhpDoc and learn with SitePoint. Our web development and design tutorials, courses, and books will teach you HTML, CSS, JavaScript, PHP, Python, and more.

  11. How to create effective PHP project documentation with Read the Docs

    Basic concept Typically, people are using Read the Docs with a tool called Sphinx. If you are writing in Python, it's also possible to use the autodoc Sphinx plugin to add API documentation, based on docstrings in the code. PHP programmers are already spoiled for choice if they want to produce HTML documentation from their code.

  12. The PHP Handbook

    PHP is an incredibly popular programming language. Statistics say it's used by 80% of all websites. It's the language that powers WordPress, the widely used content management system for websites. And it also powers a lot of different frameworks that make Web Development easier, like Laravel. Speaking of Laravel, it.

  13. Documenting PHP Code with PHPDocumentor

    Regenerating the documentation produces a table of contents consisting of links to the circlePackage and squarePackage. Clicking on each link will take you to a document similar to that found in Figure 2. Building the Documentation. You can build the project documentation using the command-line script phpdoc, or a Web-based interface.

  14. Code commenting and PHP documentation generation

    How to write them? Where they are necessary and where they are not? How to comment code correctly? How to create the same documentation style for all members of the team? What are the tools for documentation generation? I will try to answer all the questions and share with you my ideas about this question.

  15. phpDocumentor Guide to Creating Fantastic Documentation

    In essence, there may need to be two separate sets of documentation! phpDocumentor can be used to create this option using a few things. First, using the command-line file-selection options, one can write two sets of documentation, one for end-users, and the other for programmers, and put them in different subdirectories.

  16. Creating effective technical documentation

    Good documentation is like a piece of the puzzle that makes everything click — the key for encouraging feature adoption. To support you in creating effective technical documentation, this article provides an overview of the core principles of technical writing. It also highlights the best practices for creating clear and accessible documentation.

  17. Auto-generate your documentation for a PHP7 API

    Conclusion. Now, you can generate your API doc on the fly for your PHP project ! Of course there are a lot of possibilities: the swagger-php by Zircote is full of examples to use to fit with your ...

  18. How to document REST API project written in PHP using Swagger ...

    Step 1 - Initialize composer.json and require the zircote/swagger-php library. We also add script to generate swagger.json file which will be later used to open HTML documentation. Step 2 - Write example API documentation. Note that we write comments in the plain PHP file.

  19. How to Write PHP Comments (and best practices)

    You can quickly write PHP comments by three methods: Use double forward slashes: // This method is only used for single-line comments. Forward slash and asterisk - Block type: /* (open) and */ (close) This method can be used for both single-line and multiline comments. Use hash sign: #

  20. Blade Templates

    In fact, all Blade templates are compiled into plain PHP code and cached until they are modified, meaning Blade adds essentially zero overhead to your application. Blade template files use the .blade.php file extension and are typically stored in the resources/views directory.

  21. php

    php - adds PHP syntax highlighting to the content and includes a line number on every line. ... while writing EXTENDED DOCUMENTATION.So you should first focus on the meaning of EXTENDED DOCUMENTATION also known as TUTORIALS.And the meaning of PARSE ITS CONTENTS : PhpDocumentator should be able to "understand" the comments (recognize the PHP ...

  22. Credits and deductions for individuals

    How they work. You can claim credits and deductions when you file your tax return to lower your tax. Make sure you get all the credits and deductions you qualify for.

  23. Choosing a Runtime

    Edge runtime-powered functions can be a cost-effective option and provide benefits like:. Lightweight with a slim runtime - With a smaller API surface area and using V8 isolates, Edge runtime-powered functions have a slim runtime. However, only a subset of Node.js APIs are exposed; Globally distributed by default - Vercel deploys all Edge Functions globally across its Edge Network, which ...

  24. Best practices for prompt engineering with the OpenAI API

    Write a short inspiring poem about OpenAI, focusing on the recent DALL-E product launch (DALL-E is a text to image ML model) in the style of a {famous poet} 4. Articulate the desired output format through examples. Less effective : Extract the entities mentioned in the text below. Extract the following 4 entity types: company names, people ...

  25. Stomp

    Connectivity > Protocols > Stomp. ActiveMQ Classic supports the Stomp protocol and the Stomp - JMS mapping. This makes it easy to write a client in pure Ruby, Perl, Python or PHP for working with ActiveMQ Classic.. Please see the Stomp site for more details. Spec Compliance. ActiveMQ Classic v5.6 implements the Stomp v1.1 spec except for allowing spaces at the beginning or end of message ...

  26. How to use Copilot Pro to write, edit, and analyze your Word ...

    To try this, open the document you want to summarize and then click the Copilot icon on the Ribbon. Also: The best AI chatbots The right sidebar displays several prompts you can use to start your ...

  27. Create a form in Word that users can complete or print

    Show the Developer tab. If the developer tab isn't displayed in the ribbon, see Show the Developer tab.. Open a template or use a blank document. To create a form in Word that others can fill out, start with a template or document and add content controls.