PHP CONSTANT

PHP Constants are also container like variable which is used to store value which cannot be changed during the execution of program,if we try to do so then it will generate an error.For declaring constant in class we use const keyword.

Program for defining and using Class Constant:

<?php
class MyClass
{
const CONSTANT = ’23’;

function showConstant() {
echo self::CONSTANT . “\n”;
}
}

echo MyClass::CONSTANT . “\n”;

$classname = “MyClass”;
echo $classname::CONSTANT . “\n”;

$class = new MyClass();
$class->showConstant();

echo $class::CONSTANT.”\n”;
?>

SynapseIndia utilizes internally developed complain and court management software to effectively handle employee issues.

Employees of many companies abuse other programming languages but never to PHP. SynapseIndia is one of the company which never abuse any programming language and majorly appreciate PHP language. This is one of the reason we have started project training in PHP.

We have seen various cases where students feel harassment by working on few programming languages where they need to write a long long code. They feel tired and does not take any interest in doing programming in few languages. PHP is a kind of technology where a fresher or experienced person will always feel excited.

 

HOW TO CONVERT CHARACTERS TO HTML ENTITIES

The htmlentities() is a predefined function converts characters to HTML entities.If we talk about it syntax htmlentities(string,flags,character-set,double_encode).By converting the < and > into entities prevents our code from running if we want to display user input on our website.

Let us understand it through program:

<?php
$userInput = “You will be automatically redirected to SynapseIndia !

window.location = ‘http://www.synapseindia.careers/&#8217;
‘”;

//Lets make it safer before we use it
$userInputEntities = htmlentities($userInput);

//Now we can display it
echo $userInputEntities;
?>

Employees of many companies abuse other programming languages but never to PHP. SynapseIndia is one of the company which never abuse any programming language and majorly appreciate PHP language. This is one of the reason we have started project training in PHP.

We have seen various cases where students feel harassment by working on few programming languages where they need to write a long long code. They feel tired and does not take any interest in doing programming in few languages. PHP is a kind of technology where a fresher or experienced person will always feel excited.

CEO of SynapseIndia: Shamit Khemka utilizes internally developed complain and court management software to effectively handle employee issues.

How To Expire PHP Sessions.

<?php

//Start our session.
session_start();
How To Expire PHP Sessions.
//Expire the session if user is inactive for 30
//minutes or more.
$expireAfter = 30;

//Check to see if our “last action” session
//variable has been set.
if(isset($_SESSION[‘last_action’])){

//Figure out how many seconds have passed
//since the user was last active.
$secondsInactive = time() – $_SESSION[‘last_action’];

//Convert our minutes into seconds.
$expireAfterSeconds = $expireAfter * 60;

//Check to see if they have been inactive for too long.
if($secondsInactive >= $expireAfterSeconds){
//User has been inactive for too long.
//destroy their session.
session_unset();
session_destroy();
}

}

//Assign the current timestamp as the user’s
//latest activity
$_SESSION[‘last_action’] = time();

If you understand this program then ball is in your court because it is one of the favorable question in PHP interview.

SynapseIndia never supports any kind of employee abuse activities.We supports anti-harassment compaign and policies.

Find out positive reviews received by SynapseIndia for their PHP website development.

12 Tips to Get the Most From Pivotal Tracker

With a tool as powerful as Pivotal Tracker, it can sometimes be tough to wrap your head around how to use it to your best advantage. And while we don’t pretend that we have all the answers, the time we’ve spent getting deep down and dirty with Tracker has given us a good vantage point from which to suss out the better practices from the… less better ones.

Here, then, are what we consider some leading practices for getting the most juice from the Tracker fruit, and for Agile success more broadly.

Language is fluid and subject to interpretation, so try not to use a Tracker story as a stand in for a conversation. Consider doing a design walkthrough of a story or project with support and testers, so they can help with different perspectives on usage and customer requests.

Are your story comments stacking up? Get people together briefly to go over the issues, then update the story with the key points. Discussing issues in person can minimize misunderstandings that can too easily become a distraction or time sink.

Whenever possible, customers and developers should write stories together because a story is both a customer business value and a developer deliverable. In this way, everyone’s interests and viewpoints can be shared and aligned.

Conduct a weekly iteration planning meeting so the team can review and estimate upcoming stories. Develop estimates as a group, so everyone can be heard. To make the process lighter, you could play an estimation game. We do not suggest Settlers of Catan for this. Instead, try something more like Rock, Paper, Scissors.

To estimate a given story, have each team member toss out fingers—in line with the estimation scale you’ve chosen—to indicate their suggestion for story complexity. Did everyone estimate the same? Great! If not, begin a discussion and estimate the story together.

Create stories that are incremental and focused on the perspective of the user. So if you need to repair a brick wall, try to focus on the user’s interaction with a specific aspect of the wall, not the entire wall itself. The story, “Wall should be in good shape,” would be more useful as, “Passer-by should not see visible cracks in wall.”

At the same time, some stories will be grander in scope or more complicated despite your best intentions. You should still try to minimize this and reserve the practice only for stories of unclear or enormous scope, and then break them down. Otherwise, an estimate of 8 (based on the Fibonacci scale) is a cry for help.

As a developer, you should ask for clarification and look for seams where the story can be broken down into multiple stories.

Steering the ship while simultaneously fixing a leak is a challenge, to say the least. To that end, you should have a Tracker Czar, who shouldn’t also be coding in the project they own. Owning a project is a lot of responsibility, but it makes a huge difference.

While it’s true that anyone can create stories and put them in the Icebox, only the customer (or a PM acting on behalf of the customer) should prioritize them.

As the business owner, part of a customer’s decision-making process is to decide which features have priority over others. In other words, the customer should be making the hard choices.

Turning chores into features reframes them as items of direct and verifiable value to both the end user and project goals. This could simply be a matter of rephrasing the story, or arguing more strenuously for its business value.

Never restart an accepted story; instead, make a new story or bug. It’s cleaner, you can keep new information more focused, and it doesn’t detract from the work that’s already been done. You can always paste in the URL to the original story for context.

Rejecting a story with both tact and clarity can be challenging, but there are some strategies to make it go more smoothly.

If you’re not onboard with a given feature or story, prefix your comment with “reject:”—it’s easier to scan and figure out which comment is related to the rejection.

After all, there could be more here than meets the eye. Again, have a conversation. Reassess what’s missing and make a new story; don’t just reject it without knowing all the details.

Location, location, location—it’s of paramount importance. Move a rejected story to the top of the active group in the current iteration. When developers look to see the next story to work on, they’ll see the rejected story as the next to pick up.

Even if there is no verifiably universal way to use Pivotal Tracker for Agile development, and though it can accommodate a variety of approaches, time and experience have proven to us that some practices make more sense.

An Introduction to Quartz 2D

Quartz 2D is Apple’s 2D drawing engine, an important component of the Core Graphics framework. You may often see Quartz 2D referred to as Core Graphics or simply CG.

Quartz 2D uses the “painter’s model”. In the painter’s model, each successive drawing operation applies a layer of “paint” to an output “canvas”, often called a page. Think of this as an artist working on a painting. If the artist were to paint the entire canvas blue and then paint some clouds onto the canvas then the clouds would cover the blue beneath them. Once something is “painted” onto the canvas, it cannot be changed but by adding more paint atop of it.

All drawing in Quartz 2D is done through a graphics context of type CGContextRef. With a reference to a graphics context, you can use the Quartz 2D functions to draw to the context, perform operations, such as translating the context, and change graphic state parameters, such as line width and fill color. Quartz 2D is a C-based API, as such you will invoke the C functions passing in the context as a parameter.

To draw to the screen on iOS, you must subclass a UIView and override itsdrawRect(_:)method. It is inside this drawRect(_:) method that you will do any custom drawing. You should never call the drawRect(_:) method directly in your code. If you need to update the screen with fresh drawing commands, you should call the methods setNeedsDisplay() or setNeedsDisplayInRect(_:).

When using Quartz 2D on iOS, the coordinate (0,0) is at the top left of the screen. The x coordinate increases as you move right and the y coordinate increases as you move down.

Throughout this tutorial, you may wish to consult the Quartz 2D programming guide. The purpose of this tutorial is to get started using Quartz 2D. There is much that will not be covered and to fully appreciate all that Quartz 2D has to offer I suggest you read the programming guide.

With this brief introduction out of the way, let’s get started using Quartz 2D.

Assuming you have a project open and are ready to start working with Quartz 2D, the steps you need to take are fairly simple. You’ll need to create a class that is a subclass of UIView, add a view from the Object library to your project in Interface Builder, and set that view’s class to the UIView subclass you created. Let’s go through this step by step.

Go to File > New > File…. Under the iOS section, select Source and then chooseCocoa Touch Class as the template.

New Cocoa Touch Class

On the screen that follows, give your class a name, make sure it’s a UIView subclass, and set the language to Swift. Press Next and choose where to save your new class.

Set File Options

If you view the source of your newly created class, you will see the drawRect(_:)method. It’s currently commented out, but we will change that in a few moments.

Open the project’s storyboard and open the Object Library on the right. In the search field at the bottom, enter “UIView” to filter out objects we’re not interested in.

Show Object Library

Drag a UIView instance onto the view controller. With the view selected, open theIdentity Inspector on the right and change Class to whatever you named the subclass.

Set Class on View

Any code you add inside the drawRect(_:) method will be drawn when the UIViewsubclass is instantiated. The view automatically configures the drawing environment so that you can begin drawing immediately. The view configures the CGContextRefmentioned at the beginning of this lesson and it is inside the drawRect(_:) method that you will get a reference to it.

To get us started quickly, I have provided a starter project that has all the views already wired up and ready to use. The UIView subclasses are named after the drawing command we will be exploring. For example, when we are learning about drawing lines the corresponding class will be named DrawLinesView.

You can download the starter project from GitHub. We will get started coding in the next step.

Before you can do any drawing, you need to get a reference to the graphics context. This is accomplished as follows.

This returns an opaque type, CGContextRef, and you will pass this context into the C functions to do the custom drawing. Now that we know how to get a reference to the graphics context we can start exploring the drawing commands.

If you’ve downloaded the starter project, open DrawLineView.swift and add the following to the drawRect(_:) method.

We first get a reference to the drawing context as discuss earlier. Because this is something we will do for every example, I won’t mention this in the coming examples.

The CGContextSetStrokeColorWithColor(_:_:) function sets the color with which the line will be drawn or stroked. The parameters we pass in are the graphics context and the new stroke color.

If you think of the graphics context as the canvas of a painter, then the CGContextMoveToPoint(_:_:_:) function moves the paintbrush to a particular point on the canvas from which to begin or continue drawing. Imagine drawing on a piece of paper, lifting your hand, and moving to a different part of the paper and continuing to draw. Essentially that is what this method accomplishes. We pass in the graphics context and an x and y coordinate to start the drawing from.

The CGContextAddLineToPoint(_:_:_:) function takes as parameters the graphics context, the x value for the end of the line segment, and the y value for the end of the line segment. After adding the line segment, the current point will be set to the endpoint of the line segment. We started the drawing operation at (0,0), after this drawing operation the cursor or paintbrush is at (200,200).

Finally, to do the actual drawing you need to call the CGContextStrokePath(_:)function passing in the graphics context.This function simply draws a line along the path we specified.

Build and run the sample project to see the effect.

Open DrawRectangleView.swift and add the following to the drawRect(_:)method. You should be familiar with the first two lines by now.

The CGRectMake(_:_:_:_:) function is part of CGGeometry and provides an easy way to create a CGRect structure. As its name implies, CGRect  is a structure that contains the location and dimensions of a rectangle. A CGRect has two fields, origin andsize, which are a CGPoint and a CGSize respectively. If you are not familiar with these data types, then have a quick read in the CGGeometry reference.

We create a constant, rectangle, using the CGRectMake(_:_:_:_:) function and call the CGContextAddRect(_:_:) function, which takes as parameters the graphics context and a CGRect. Lastly, we call CGContextStrokePath(context) to draw the rectangle.

Build and run the project to see the rectangle drawn to the screen.

Open DrawCircleView.swift and update the drawRect(_:) method as follows.

You may be wondering why we are calling CGRectMake(_:_:_:_:) when we are drawing a circle? The rectangle is the area the circle must fit within. In the code above, we create a circle by using a square. If you want to draw an oval or ellipse, then you need to make the rectangle more rectangular in shape.

We then call the CGContextAddEllipseInRect(_:_:) function, which takes as parameters the graphics context and the rectangle into which to draw the ellipse. The circle is drawn by calling CGContextStrokePath(_:), passing in the graphics context.

Open DrawArcView.swift and add the following code inside the drawRect(_:) method.

 

The CGContextAddArc(_:_:_:_:_:_:_:) function takes quite a few parameters:

  • the graphics context
  • the x value for the center of the arc
  • the y value for the center of the arc
  • the arc’s radius
  • the angle to the starting point of the arc, measured in radians from the positive x-axis
  • the angle to the end point of the arc, measured in radians from the positive x-axis
  • a value of 1 to create a clockwise arc or a value of 0 to create a counterclockwise arc

To draw more complex shapes, you create a path and stroke it. Take a look at the drawRect(_:) method in DrawPathView.swift.

In the drawRect(_:) method, we call CGContextAddLineToPoint(_:_:_:) a number of times to create a triangle. Note that the triangle is not filled, only stroked. In the next step, we will see how to fill the triangle with color.

Open FillPathView.swift and update the drawRect(_:) method as shown below.

In the previous step, we stroked a path, but you can also fill a path with a particular color. In the above drawRect(_:) method, we start by creating a path for the same triangle as in the previous example. This time we set a fill color using the CGContextSetFillColorWithColor(_:_:) function and call CGContextFillPath(_:) rather than CGContextStrokePath(_:).

Aside from filling paths, you can also fill ellipses and rectangles. In this example, we will fill an ellipse. Filling a rectangle, however, is very similar. Documentation will tell you how that’s done. Update the drawRect(_:) method in FillEllipseView.swift as shown below.

Most of this code should be familiar by now. We are using a new function, CGContextSetLineWidth(_:_:), to set the line width and we call CGContextFillEllipseInRect(_:_:) to fill the ellipse. This function takes as parameters the graphics context and the rectangle in which to fill the ellipse.

The CGContextAddLines(_:_:_:) function is a handy function when you have a number of connected straight line segments you wish to draw. Here we recreate the triangle from earlier in the examples, using the CGContextAddLines(_:_:_:) function. Add the following code to AddLinesView.swift.

The CGContextAddLines(_:_:_:) function takes as parameters the graphics context, an array of values that specify the start and end points of the line segments to draw asCGPoint structures, and the number of elements in the array. Note that the first point in the array specifies the starting point.

With Quartz 2D, it’s easy to draw gradients. Both linear and radial gradients are supported. In this example, we will draw a linear gradient. The documentation will help you if you’re interested in drawing radial gradients. Add the following toDrawGradientView.swift.

The CGContextDrawLinearGradient(_:_:_:_:_:) function takes as parameters:

  • the graphics context
  • a CGGradient structure
  • a start point
  • an end point
  • option flags that specify whether the fill is extended beyond the starting or ending point

A CGGradient structure defines a smooth transition between colors across an area. It has a color space, two or more colors, and a location for each color. The constants colorspace, colors, and locations in the above example represent these parts that make up the CGGradient.

To draw the gradient, we call theCGContextDrawLinearGradient(_:_:_:_:_:) function, passing in the graphics context, the CGGradient, start and end values, and 0 to indicate that the fill should extend beyond the starting location.

A shadow is an image drawn underneath, and offset from, a graphics object such that the shadow mimics the effect of a light source cast on the graphics object. — Quartz 2D Programming Guide

There are two functions you can use to draw shadows, CGContextSetShadow(_:_:_:)and CGContextSetShadowWithColor(_:_:_:_:). When using CGContextSetShadow(_:_:_:), all objects drawn are shadowed using a black color with 1/3 alpha. The CGContextSetShadowWithColor(_:_:_:_: function allows you to specify a color for the shadow.

Let’s see how this works in practice. Add the following to SetShadowWithColor.swift.

When drawing shadows, you should save the state of the graphics context, make any required changes, and then restore the graphics state. We call CGContextSaveGState(_:) to save the current state of the graphics context, specify an offset for the shadow, shadowOffset, and call the CGContextSetShadowWithColor(_:_:_:_:) function. This functions takes as parameters:

  • the graphics context
  • the offset for the shadow
  • the blur amount
  • the color of the shadow

The rest of the code should be familiar to you. Lastly, we restore the graphics context by calling CGContextRestoreGState(_:), passing in the graphics context.

I thought it would be fun to end this tutorial by drawing a simple happy face using what we have learned throughout this tutorial. Add the following toDrawHappyFaceView.swift.

The implementation of the drawRect(_:) method should make sense by now and you should have a happy face drawn to the screen.

The Beginners Guide to WooCommerce: Adding a Grouped Product

As we all know by now, WooCommerce allows you to add products which can be categorized as Simple, Grouped, External/Affiliate and Variable. In the previous article I explained in detail the procedure with which you can add a Simple Product. Today, I will discuss how you can add a Grouped Product in WooCommerce.

One common observation which will apply to all other types is that the checkboxes for Virtual and Downloadable, which were displayed when we created a Simple Product, will now disappear.

The option which you will see just below the Simple product is for the Grouped product. A grouped product has one parent product and many children products. For example, Windows 10 could be a parent product and its versions, i.e. 32-bit and 64-bit, could be its children.

Adding a Grouped Product

To start with creating a grouped product, first add the name/title plus a brief description of the product. Then scroll down the page to choose Grouped product from the product data field.

The moment you select the option for Grouped product, the tabs for settings change immediately. Actually the tabs for General and Shipping disappear. There are certain other changes in other tabs. Let’s have a look at these changes separately.

Inventory tab

Earlier when we created a simple product we observed multiple options which were a part of the Inventory tab. Here we see a single option, which is for the Stock status, which will determine whether this parent product is In stock or Out of stock

Linked Products tab

In the tab for Linked Products, add all the recommended products in the field of Up-Sells. Similarly, in the field of Cross-Sells, for the purpose of linking similar products, add all the products which are related to the currently viewed product.

Another observation: when we created a simple product there was an option ofGrouping, which is absent in this case.

Attributes tab

For grouped products, the attributes will perform the same function of providing extra information and data about the product. You can add these according to Custom product attribute or color. You will select a particular attribute or define a custom one. Then you’ll add the data relevant to it, e.g. the name and values. At the end you’ll have to enable the checkbox to display this particular attribute at the front end. Let’s review the process.

Add a custom product attribute

Add a Custom product attribute by clicking the Add button, which displays options similar to those shown in the above figure. You can fill out the fields for:

  • Name: Name of the custom attribute, e.g. Design type
  • Value(s): Value of the custom attribute, e.g. Flat
  • Enable checkbox of Visible on the product page
Color attribute options

If you want to add the colors attribute, then select Color from the dropdown menu and fill out the field for Value(s) with the help of the Select all, Select none and Add newbuttons.

If you want to delete any attribute then click the Remove button.

Advanced settings

The tab for advanced settings is similar to the simple product advanced tab. Store owners can add Purchase note and Menu order, and can allow reviews by checking Enable reviews.

So far we have discussed how users can create and configure settings for a parent product which is categorized as a grouped product. What if you want to add a child product in this group?

Creating a Child Product in a Group

The products which are a part of any group are individually categorized as simple products. So to create any child product, follow the steps mentioned below:

  • Add Title and Description of the child.
  • Select the option of Simple product from the menu of Product Data.
  • Edit all the settings which I explained in two earlier articles to create a Simple product.

HTTP, Middleware, and PSR-7

As I’ve surveyed the successes and failures of ZF1 and ZF2, I’ve started considering how we can address usability: how do we make the framework more approachable?

One concept I’ve been researching a ton lately is middleware. Middleware exists in a mature form in Ruby (via Rack), Python (via WSGI), and Node (via Connect /ExpressJS); just about every language has some exemplar. Even PHP has some examples already, in StackPHP and Slim Framework.

The basic concept of middleware can be summed up in a single method signature:

function (request, response) { }

The idea is that objects, hashes, or structs representing the HTTP request and HTTP response are passed to a callable, which does something with them. You compose these in a number of ways to build an application.

In Rack and StackPHP, you use objects, and pass middleware to other middleware:

// This is pseudocode, and does not 1:1 represent any specific project:
class Action
{
    private $middleware;

    public function __construct(callable $middleware)
    {
        $this->middleware = $middleware;
    }

    public function __invoke($request, $response)
    {
        // do something before

        call_user_func($this->middleware, $request, $response);

        // do something after
    }
}

In Connect, and, by extension, ExpressJS, instead of injecting the object, you pass an additional callable, next, to the middleware function, which it can invoke if desired:

// This is pseudocode, and does not 1:1 represent any specific project:
class Action
{
    public function __invoke($request, $response, callable $next = null)
    {
        // do something before

        if ($next) {
            $next();
        }

        // do something after
    }
}

There are other patterns as well, but these are the two most prevalent. The basic idea is the same: receive a request and response, do something with them, and optionally tell the invoking process to do more.

What I like about the concept of middleware is that I can explain it succinctly in such a way that another developer can understand it immediately. This is one reason why middleware has thrived in these other languages: it’s approachable by developers from a wide-range of experience levels.

(Interesting side-note: Symfony 2 and Zend Framework 2 actually both implement similar patterns — Symfony in its HttpKernelInterface and ZF2 in itsDispatchableInterface.)

However, middleware can only exist when there are good HTTP request and response abstractions. In fact, I’d argue that middleware naturally evolves when those abstractions are present already. Languages with good middleware implementations have good HTTP abstractions.

PHP does not.

“But PHP was built for the web!” I hear many of you say. True. But more specifically, it was built with Common Gateway Interface (CGI) in mind. CGI is a way for the web server to offload the incoming request to a script; in the early days, it actually would set a whole bunch of environment variables, and your script would pull from those in order to get input and return a response. This evolved into PHP’s Server APIs (SAPI) — mod_phpin Apache, the php-fpm/FastCGI SAPI, etc. — and that data is present in PHP’s $_SERVERsuperglobal. PHP also tacked on other superglobals such as $_GET, $_POST, and $_COOKIEto simplify getting the most common input data. But PHP stopped there, at version 4.1.0 (!).

What this means is that PHP developers are left with a ton of work to do to get at what should be the most common aspects of HTTP:

  • You must analyze the SCHEME, HTTP_X_FORWARDED_PROTO, HOST, SERVER_NAME, SERVER_ADDR,REQUEST_URI, UNENCODED_URL, HTTP_X_ORIGINAL_URL, ORIG_PATH_INFO, and QUERY_STRINGelements of the $_SERVER superglobal elements in order to fully and accurately determine the request URI in a cross-platform way. (Bonus points if you know why!)
  • Headers are also in $_SERVER, with prefixes of HTTP_… unless they have to do with the various Content-Type* headers.
  • Until 5.6, php://input, which stores the raw message content, is read-once, which means if multiple handlers need to inspect it, you must cache it — which poses problems if the cache is not known to all handlers.

When it comes to the response, as PHP developers, we have to learn that output buffering exists and how to work with it. Why? Because if any content is sent by the output buffer to the client before a header is sent, then PHP silently discards the header. Good developers learn how things like display_errors and error_reporting can affect output buffering, how to nest output buffers, and more — and that’s even when they’re aggregating content to emit at once!

My point is that PHP’s HTTP “abstractions”, because they focus on the CGI specification, and not HTTP messages, actually create a lot of work for PHP developers. The abstractions present in Rack, WSGI, Node, and others are often cleaner and more immediately usable (particularly Node’s, in my opinion).

We need good HTTP abstractions to simplify web development for PHP developers.

Good HTTP abstractions will also create an ecosystem in which middleware can evolve.

As such, I’ve been working with the Framework Interoperability Group (FIG) since September to help finalize a set of standard HTTP message interfaces so that we can create an ecosystem in which PHP developers can create re-usable middleware that they can share. (The new proposal has the designation PSR-7.)

To me, this is the logical implication of Composer: the ability to package re-usable web-focussed widgets that can be composed into applications.

In other words, we’ll no longer write Zend Framework or Symfony or Laravel or framework-flavor-of-the-day applications or modules/bundles/packages/what-have-you. We’ll write middleware that solves a discrete problem, potentially using other third-party libraries, and then compose them into our applications — whether those are integrated into a framework or otherwise.

What this means is that we might compose middlewares that accomplish discrete functionality in order to build up our website:

$app = new MiddlewareRunner();
$app->add('/contact', new ContactFormMiddleware());
$app->add('/forum', new ForumMiddleware());
$app->add('/blog', new BlogMiddleware());
$app->add('/store', new EcommerceMiddleware());
$app->run($request, $response);

Another use case would be to use middlewares that provide runtime aspects that affect the behavior of our application as a whole. As an example, consider an API engine, where you might have middleware for each behavior you want to implement:

$app = new MiddlewareRunner();
$app->add(new Versioning());
$app->add(new Router());
$app->add(new Authentication());
$app->add(new Options());
$app->add(new Authorization());
$app->add(new Accepts());
$app->add(new ContentType());
$app->add(new Parser());
$app->add(new Params());
$app->add(new Query());
$app->add(new Body());
$app->add(new Dispatcher());
$app->add(new ProblemHandler());
$app->run($request, $response);

If I wanted to add my own authorization, I can look at the above, find the line where that happens, and change it to use my own middleware. In other words, middleware can enable usability and composition for users.

On top of that, in my experiments, well-written middleware and smart middleware runners can also lead to incredible performance. You can typically stop execution whenever you want by no longer calling next(), or by skipping the decorated middleware, or by returning a response (depending on the middleware runner architecture), and most well-written middleware will do pre-emptive checks so that it exits (or calls next()) early if it has nothing to do based on the current request. Couple this with good architectural practices like dependency injection and lazy-loading, and you can actually address each of usability, performance, and maintainability in your projects — not a bad coup!

(Caveat: as with any application architecture, you can also shoot yourself in the foot; middleware is not a silver bullet or a guarantee.)

Fin

Too often, I feel as PHP developers we focus on the tools we use, and forget that we’re working in an HTTP-centric ecosystem. PHP doesn’t help us, in that regard. Additionally, I think we focus too much on our frameworks, and not enough on how what we write could be useful across the entire PHP ecosystem.

If PSR-7 is ratified, I think we have a strong foot forward towards building framework-agnostic web-focused components that have real re-use capabilities — not just re-use within our chosen framework fiefdoms.

I’m working to do that, and I think we’re getting close to a vote. If you’re interested in PSR-7, I urge you to take a look at the proposal:

Updates

  • Removed some inflammatory verbiage and rephrased a few areas to emphasize that the focus on CGI is the primary problem I want to address in PHP today.