Laravel now has a changelog
It's quite surprising that Laravel didn't have a changelog until today. Community member Till Krüss added one and will probably maintain it in the foreseeable future. The changelog can be viewed on GitHub.
Posts tagged with open source
It's quite surprising that Laravel didn't have a changelog until today. Community member Till Krüss added one and will probably maintain it in the foreseeable future. The changelog can be viewed on GitHub.
Imagine you are working on new app. Your client wants to see the progress that you've made. However your site isn't ready for prime time yet. Sure, you could create some login functionality and display the site only to logged in users. But why bother creating users when there is a more pragmatic approach?
At Spatie we often instruct a client to visit /demo. Visiting that url will unlock access to the entire front site. Because creating packages has many benefits we decided to open source our solution.
Our newly released laravel-demo-mode package blocks your work in progress from prying eyes. After it is installed you can use a route macro to register a route that grants access to the protected routes:
Route::demoAccess('/demo');
Routes can be protected by using the demoMode-middleware on them:
Route::group(['middleware' => 'demoMode'], function () {
Route::get('/secret-route', 'SecretController@index');
});
Unless a user has first visited /demo first, he or she will be redirected to /under-construction. This url can be changed in the config file.
A word to the wise: do not use this package to restrict access to sensitive data or to protect an admin section. For those cases you should use proper authentication.
You can take a look at the package on GitHub. If you like it, you might like some of our other Laravel packages as well.
Join thousands of developers
Every two weeks, I share practical tips, tutorials, and behind-the-scenes insights from maintaining 300+ open source packages.
No spam. Unsubscribe anytime. You can also follow me on X.
In the JavaScript world converting modern code to an older syntax is quite common. In the PHP world you don't see that happen often. Symfony provides a few polyfills, but a full fledged conversion isn't available. At the meetup of our local PHP user group Jens Segers, Hannes Van de Vreken and I were toying around with the idea of converting PHP 7 code to equivalent PHP 5 code automatically.
Today our little hobby project called 7to5 was tagged 1.0.0. You can view the repo on GitHub.
Because there are a lot of small things that cannot be detected and/or converted properly it is not guaranteed that the converted code will work. It's highly recommended to run your automated tests against the converted code to determine if it works.
composer install global spatie/7to5
Once that's done you can use php7to5 to convert a whole directory in one go:
php7to5 convert {$directoryWithPHP7Code} {$destinationWithPHP5Code}
Image how you would convert this:
class Test
{
public function test()
{
$class = new class() {
public function method(string $parameter = '') : string {
return $parameter ?? 'no parameter set';
}
};
$class->method();
$anotherClass = new class() {
public function anotherMethod(int $integer) : int {
return $integer > 3;
}
};
}
}
to this:
class AnonymousClass0
{
public function method($parameter = '')
{
return isset($parameter) ? $parameter : 'no parameter set';
}
}
class AnonymousClass1
{
public function anotherMethod($integer)
{
return $integer < 3 ? -1 : ($integer == 3 ? 0 : 1);
}
}
class Test
{
public function test()
{
$class = new AnonymousClass0();
$class->method();
$anotherClass = new AnonymousClass1();
}
}
After the meetup of our usergroup the idea lay dormant for a while, but at this year's PHPUKConference Hannes decided to just do it™. I was immediately pulled in. We ran over a few options. It quickly became apparent that using regex was out of the question. Using a state machine would become very unwieldy fast too. We settled on using the PHP parser tool created by Nikita Popov. This tool can convert PHP code to an abstract syntax tree. It's very similar to a domtree for html code. Here's an example (taken from the php parser docs). This code:
echo 'Hi', 'World';
hello\world('foo', 'bar' . 'baz');
will get converted to this tree:
[
0: Stmt_Echo(
exprs: [
0: Scalar_String(
value: Hi
)
1: Scalar_String(
value: World
)
]
)
1: Expr_FuncCall(
name: Name(
parts: [
0: hello
1: world
]
)
args: [
0: Arg(
value: Scalar_String(
value: foo
)
byRef: false
)
1: Arg(
value: Expr_Concat(
left: Scalar_String(
value: bar
)
right: Scalar_String(
value: baz
)
)
byRef: false
)
]
)
]
Here's the code to create the abstract syntax tree.
//create a parser
$parser = (new PhpParser\ParserFactory())->create(PhpParser\ParserFactory::PREFER_PHP7);
//feed it PHP 7 code
$php7code = file_get_contents($pathToPhp7File);
//this variable now contains the entire syntax tree
$syntaxTree = $parser->parse($php7code);
Now that we have created the abstract syntax tree, let's manipulate it. The tree can be traversed by a Traverser. The manipulation can be done by one or more Visitors objects. Let's view some code that traverses the tree and converts it back to regular PHP code.
$traverser = new PhpParser\NodeTraverser();
$traverser->addVisitor(new NullCoalesceReplacer());
$manipulatedTree = $traverser->traverse($syntaxTree);
//convert the tree back to regular code
$code = (new \PhpParser\PrettyPrinter\Standard())->prettyPrintFile($manipulatedTree);
file_put_contents($pathToFileWithManipulatedPhpCode, $code);
The real magic happens in the NullCoalesceReplacer class. It will convert all usages of the null coalesce operator, which is exclusive to PHP 7, to equivalent PHP 5 code. This class is not a part of Nikita's package. Hannes and I created it together with all other visitors.
Before taking a look at the code of that class, we'll first examine how we would manually replace a null coalesce operator.
//PHP 7 code
$result = $input ?? 'fixed-value';
//equivalent PHP 5 code
$result = isset($input) ? $input : 'fixed-value';
Let's describe the needed conversion in plain English. We'll need to create a ternary statement. The left hand side of the '??' needs to put in an isset statement. The true branch of the ternary statement needs to use the left hand side of the '??'-operator, the false branch needs the right hand side.
Here's the code of the NullCoalesceReplacer-visitor.
namespace Spatie\Php7to5\NodeVisitors;
use PhpParser\Node;
use PhpParser\Node\Expr\BinaryOp\Coalesce;
use PhpParser\NodeVisitorAbstract;
class NullCoalesceReplacer extends NodeVisitorAbstract
{
public function leaveNode(Node $node)
{
//don't do at thing if the given node is not a Coalesce operator we
if (!$node instanceof Coalesce) {
return;
}
//create an isset functional call with the left side of '??' as the first parameter
$issetCall = new Node\Expr\FuncCall(new Node\Name('isset'), [$node->left]);
//replace the entire node by a ternary statement
return new Node\Expr\Ternary($issetCall, $node->left, $node->right);
}
}
Let's review another visitor. This one will remove all scalar type hints:
namespace Spatie\Php7to5\NodeVisitors;
use PhpParser\Node;
use PhpParser\Node\Param;
use PhpParser\NodeVisitorAbstract;
class ScalarTypeHintsRemover extends NodeVisitorAbstract
{
public function leaveNode(Node $node)
{
if (!$node instanceof Param) {
return;
}
if ($this->isScalar($node->type)) {
$node->type = null;
}
}
/**
* @param string|null $type
*
* @return bool
*/
protected function isScalar($type)
{
return in_array($type, ['int', 'integer', 'float', 'string', 'bool', 'boolean']);
}
}
Using an abstract syntax tree sure makes manipulating code fairly readable. There are quite a number of other visitors. You can take a look at them on GitHub.
Meanwhile a more featured rich project that converts PHP 7 code has popped up (so if you do want to convert some PHP 7 code take a look at that one too).
Virtually every website displays some sort of menu. Generating html menus might seem simple, but it can become complex very quickly. Not only do you have to render some basic html, but you also have to manage which item is active. If a menu has a submenu you'll also want the parents of an active…
Today our team released a new major version of laravel-backup. It can backup the files and databases of your application to one or more external filesystems. It uses Laravel's native cloud filesystem to do this. The package can also notify you via Slack and/or email when something goes wrong with…
At the PHP Benelux conference James Titcumb did a presentation on the BetterReflection library he's working on. You can view the slides of his presentation on SlideShare.
The BetterReflection library has a few advantages over PHP's native reflection capabilities (copied from the docs):
Consider this class:
class MonkeyPatchMe
{
function getMessage() : string
{
return 'hello everybody';
}
}
The body of the getMessage-function can be replaced using this code:
$classInfo = ReflectionClass::createFromName('MonkeyPatchMe');
$methodInfo = $classInfo->getMethod('getMessage');
$methodInfo->setBody(function() {
return 'bye everybody';
});
$monkeyPatchedClass = new MonkeyPatchMe();
$monkeyPatchedClass->getMessage() // returns 'bye everybody'
Behind the scenes this voodoo works by copying the original class to another file, doing a replacement of the function body there and loading up that class.
I'll be keeping my eye on how the BetterReflection library evolves. You can read all about it's current functionality in the docs on GitHub.
Last week Jan Oris gave a talk on creating your own development tools at the Limburg PHP User Group. He touches on the why and how of creating packages as well. I hope some of you will start creating packages too after seeing this.
https://youtu.be/KTdA7kf2cUM?t=1m21s
At the end of this month our local user group, PHP Antwerp, will hold it's third meetup. It'll be sponsered by Spatie, of which I'm a co-owner. In this post I'd like to explain why we are sponsering this event. Of course as a company it's good to get our name out there but there are other more…
Adam Wathan of Tighten Co. shared some cool code to create static sites using Laravel's Blade.
Building a Jigsaw site is exactly like building a static HTML site, except that files ending in `.blade.php` will be rendered using Laravel's Blade Templating Language.https://github.com/tightenco/jigsaw
For a project I needed to extract some text from a pdf. Although there were already a few packages that could to this, I still created spatie/pdf-to-text because I wanted something that was really easy to use. And also because it's fun creating packages. Under the hood a utility called pdftotext is…
Spatie, the company where I work, recently released a Laravel package called laravel-sluggable. It automatically creates unique slugs when saving a model. To install the package you just need to put the provided Spatie\Sluggable\HasSlug-trait on all models that have slugs. The trait contains an…
When Spatie unleashes a new site on the web we want to make sure that all, both internal and external, links on it work. To facilitate that process we released a tool to check the statuscode of every link on a given website. It can easily be installed via composer: composer global require…
At Spatie we're constantly improving our application template called Blender. We love using packages to pull in functionality. Creating and using packages has many benefits. Though we try to create public packages that benefit the community, there are some packages that are very specific to Blender.…
You may be asking yourself "Why PostgreSQL?" There are several choices for open source relational databases out there (we looked at MySQL, MariaDB and Firebird for this article), but what does PostgreSQL have that they don't? PostgreSQL's tag line claims that it's: "The world's most advanced open source database." We'll give you a few reasons why PostgreSQL makes this claim.https://www.compose.io/articles/what-postgresql-has-over-other-open-source-sql-databases/
At Spatie we use a homegrown Laravel template called Blender. It's being used on nearly all our projects. When starting with a greenfield project we take a copy of Blender and make project specific changes in that copy. We built it because we want maximum flexibility and don't want to be hampered by…
One of the most important endeavors in the PHP universe is the PHP Framework Interop group. The group consists of several maintainers of big PHP projects. Their aim is to find commonalities between their projects and find ways to work together. They do this by proposing and accepting PSR's, short for PHP Standard Recommendation.
One of the most important PSR's is PSR-4 (and the now deprecated PSR-0) which describes a way to autoload classes. Thanks to this standard packages can be easily be reused in many frameworks and projects. PSR-2 is another important one. It is a coding style guide and greatly improves readabiltiy of code when working with a bunch of developers. There are several other PSR's that have been accepted.
Today PHP-FIG published their new site. It features a beautiful design by Jonathan Reinink (he's the designer of the PHP League sites, author of Glide, and creator of the PHP Package checklist). If you use PHP in any way you owe it to yourself to check it out the new site.
Jens Segers explains how to use PHP League's shiny new version of Container. The usage of ContainerInterface seems interesting:
League's container now implements the `ContainerInterface`, which is defined by the Container Interoperability group. This is really great as there are a few projects and frameworks which support this interface. For example, the Slim 3 micro framework already allows you to choose your own container flavour, as long as it implements the interface.Read the full article at Jens' blog.
The League's Container seems like a nice alternative to PHP DI that I have been using.
As software developers we tend to look at things from our own perspective. Assuming everyone else will see it the same way. I’ve spent all this time developing but I didn’t take those extra few minutes to really polish the marketing text. This is the big mistake. I know you are thinking it’s open source, do I really need marketing? Without a doubt yes you do!http://ericlbarnes.com/open-source-marketing-tips/
While doing some research about other obfuscation techniques I stumbled upon an implementation based on Donald Knuth's integer hash. This unbelievable small and fast algorithm will generate random-like integers with the ability to convert them back to the original value. This technique was so cool that I decided to create a PHP package for it called Optimus.http://jenssegers.be/blog/67/id-transformation-with-optimus
At Spatie all our greenfield projects are powered by custom built CMS based on Laravel 5. An important part of the CMS is the medialibrary-component. It handles how uploaded files are associated with models. My intern and I recently took the time to release our medialibrary as a package on GitHub.…