Presented by Marvin Oey
https://marvoey.github.io/reveal-presentationsTaken from How to Build a Drupal Site with Composer, as Seen at DrupalCon
Composer is a dependency management tool for PHP.
It allows you to install, update, and load the PHP libraries that your PHP application depends on.
Say you have a Drupal 7 application.
... That requires jCarousel.
which is a third party, external dependency.
You download the tarball, decompress, move it into place. Voila!
Your hypothetical Drupal 7 site requires:
In Drupal 7 you would use:
That worked for dealing with a single library incompatibility.
...which uses lot of external dependencies
...and a whole lot more!
...and the list goes on.
Dependency management is a fundamental part of software development
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('SHA384', 'composer-setup.php') === '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
chmod 755 composer.phar
brew install composer
Now we can create a PHP project from scratch
# Make a directory.
$ mkdir demo
$ cd demo
# Create an empty file.
$ touch index.php
$ tree
. demo
└── index.php
...and we can initialize Composer with:
$ composer init
which creates a composer.json file
packagist.org
$ composer require monolog/monolog
This command discovers the library, determines correct version, and downloads it.
demo
├── composer.json
├── composer.lock
├── index.php
└── vendor
├── autoload.php
├── composer
├── monolog
└── psr
demo/vendor/monolog
└── monolog
├── CHANGELOG.md
├── LICENSE
├── README.md
├── composer.json
├── doc
│ ├── 01-usage.md
│ ├── 02-handlers-formatters-processors.md
│ ├── 03-utilities.md
│ ├── 04-extending.md
│ └── sockets.md
├── phpunit.xml.dist
├── src
│ └── Monolog
└── tests
└── Monolog
// Require Composer's autoloader.
require __DIR__ . "/vendor/autoload.php";
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
// Create a logger
$log = new Logger('my-log');
$log->pushHandler(new StreamHandler(__DIR__ . "/my.log", Logger::WARNING));
// Log a message!
$log->error('I did it!');
# Execute the script.
$ php -f index.php
Check to see if it works
# Look in the log file.
$ cat my.log
[2018-03-25 12:05:00] my-log.ERROR: I did it! [] []
We use it during development only to make sure our code is nicely formatted. We don’t need it to run our logger.
$ composer require squizlabs/php_codesniffer --dev
Which adds new files
demo
├── composer.json
├── composer.lock
├── index.php
├── my.log
└── vendor
├── autoload.php
├── bin
│ ├── phpcbf -> ../squizlabs/php_codesniffer/bin/phpcbf
│ └── phpcs -> ../squizlabs/php_codesniffer/bin/phpcs
├── composer
│ ├── ClassLoader.php
│ ├── LICENSE
│ ├── autoload_classmap.php
│ ├── autoload_namespaces.php
│ ├── autoload_psr4.php
│ ├── autoload_real.php
│ ├── autoload_static.php
│ └── installed.json
├── monolog
│ └── monolog
├── psr
│ └── log
└── squizlabs
└── php_codesniffer
$ ./vendor/bin/phpcs --standard=PSR2 index.php
FILE: ...rojects/drupal-vm/vm-sites/meetups/2018-10-16-epam-composer/demo/index.php
--------------------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
--------------------------------------------------------------------------------
13 | ERROR | [x] Expected 1 newline at end of file; 0 found
--------------------------------------------------------------------------------
PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY
--------------------------------------------------------------------------------
Time: 80ms; Memory: 4Mb
In less than 10 commands, we built a logging app from scratch
$ mkdir my-new-project
$ cd my-new-project
$ touch index.php
$ composer init
$ composer require monolog/monolog
# Wrote a few PHP lines.
$ php -f index.php
$ cat my.log
$ composer require squizlabs/php_codesniffer --dev
$ ./vendor/bin/phpcs --standard=PSR2 index.php
Deeper look...
{
"name": "marvin.oey/demo",
"authors": [
{
"name": "Marvin Oey",
"email": "marvin.oey@acquia.com"
}
],
"require": {
"monolog/monolog": "^1.23"
},
"require-dev": {
"squizlabs/php_codesniffer": "^3.3"
}
}
monolog/monolog package
{
"name": "monolog/monolog",
"description": "Sends your logs to files, sockets, inboxes, databases and various web services",
"keywords": ["log", "logging", "psr-3"],
"homepage": "http://github.com/Seldaek/monolog",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
}
],
"require": {
"php": ">=5.3.0",
"psr/log": "~1.0"
},
"require-dev": {
"phpunit/phpunit": "~4.5",
"graylog2/gelf-php": "~1.0",
"sentry/sentry": "^0.13",
"ruflin/elastica": ">=0.90 <3.0",
"doctrine/couchdb": "~1.0@dev",
"aws/aws-sdk-php": "^2.4.9 || ^3.0",
"php-amqplib/php-amqplib": "~2.4",
"swiftmailer/swiftmailer": "^5.3|^6.0",
"php-console/php-console": "^3.1.3",
"phpunit/phpunit-mock-objects": "2.3.0",
"jakub-onderka/php-parallel-lint": "0.9"
},
"_": "phpunit/phpunit-mock-objects required in 2.3.0 due to https://github.com/sebastianbergmann/phpunit-mock-objects/issues/223 - needs hhvm 3.8+ on travis",
"suggest": {
"graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
"sentry/sentry": "Allow sending log messages to a Sentry server",
"doctrine/couchdb": "Allow sending log messages to a CouchDB server",
"ruflin/elastica": "Allow sending log messages to an Elastic Search server",
"php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
"ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
"ext-mongo": "Allow sending log messages to a MongoDB server",
"mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver",
"aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
"rollbar/rollbar": "Allow sending log messages to Rollbar",
"php-console/php-console": "Allow sending log messages to Google Chrome"
},
"autoload": {
"psr-4": {"Monolog\\": "src/Monolog"}
},
"autoload-dev": {
"psr-4": {"Monolog\\": "tests/Monolog"}
},
"provide": {
"psr/log-implementation": "1.0.0"
},
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"scripts": {
"test": [
"parallel-lint . --exclude vendor",
"phpunit"
]
}
}
For each dependency, we typically want the latest version that won’t break our site.
But if we just get the latest version of everything, an upstream change will break something in our site.
And if we just stick to the exact versions we use now, we get no new features or bug fixes.
^1.2.3 is equivalent to =1.2.3,<2.0.0.
Downloads latest minor or patch version above specified version. Allows last 2 digits to go up.
This is the recommended approach!
^1.2.3 is equivalent to >=1.2.3,<1.3.0.
Specifies a minimum version, but allows the last digit specified to go up.
>=1.0
>=1.0,<=1.5
<=1.5
Specify a range of valid versions and combine multiple ranges with AND and OR operands.
1.0.* is equivalent to >=1.0,<1.1.
Specify a pattern with a * wildcard.
1.0.0 will download exactly 1.0.0.
dev-master uses the master branch.
Using the prefix dev- followed by a git branch name like master will checkout that branch.
Records which specific versions were actually installed.
Fundamentally changes the behavior of composer install
.
composer.lock
DOES NOT existcomposer install
will:
composer.lock
DOES existcomposer install
will:
locked in
composer update
will:
Composer has indicated that this is the best practice because it avoids the following problems:
Everyone gets the exact same dependencies.
But your repo is much lighter, and you avoid git submodule hell.
Not having vendor assumes you have scripted deployments.
But your repo is much lighter, and you avoid git submodule hell.
Don't worry, you can still commit the vendor directory if you need to.
https://github.com/drupal-composer/drupal-project
https://github.com/acquia/lightning-project
https://github.com/acquia/blt-project
https://github.com/contentacms/contenta_jsonapi_project
$ composer create-project
drupal-composer/drupal-project:8.x-dev
some-dir
--stability dev
--no-interaction
Drupal.org format | Translated semver format |
---|---|
{core.x}-{major}.{minor}-{stability} | {major}.{minor}.0-{stability} |
8.x-3.4 | 3.4.0 |
8.x-2.10-rc2 | 2.10.0-rc2 |
8.x-1.0-alpha5 | 1.0.0-alpha5 |
7.x-1.x-dev | 1.x-dev |
reveal.js enables you to create beautiful interactive slide decks using HTML. This presentation will show you examples of what it can do.
Slides can be nested inside of each other.
Use the Space key to navigate through all slides.
Nested slides are useful for adding additional detail underneath a high level horizontal slide.
That's it, time to go back up.
Not a coder? Not a problem. There's a fully-featured visual editor for authoring these, try it out at https://slides.com.
Press ESC to enter the slide overview.
Hold down alt and click on any element to zoom in on it using zoom.js. Alt + click anywhere to zoom back out.
Presentations look great on touch devices, like mobile phones and tablets. Simply swipe through your slides.
Hit the next arrow...
... to step through ...
... a fragmented slide.
There's different types of fragments, like:
grow
shrink
fade-out
fade-up (also down, left and right!)
current-visible
Highlight red blue green
You can select from different transitions, like:
None -
Fade -
Slide -
Convex -
Concave -
Zoom
reveal.js comes with a few themes built in:
Black (default) -
White -
League -
Sky -
Beige -
Simple
Serif -
Blood -
Night -
Moon -
Solarized
Set data-background="#dddddd"
on a slide to change the background color. All CSS color formats are supported.
<section data-background="image.png">
<section data-background="image.png" data-background-repeat="repeat" data-background-size="100px">
<section data-background-video="video.mp4,video.webm">
Different background transitions are available via the backgroundTransition option. This one's called "zoom".
Reveal.configure({ backgroundTransition: 'zoom' })
You can override background transitions per-slide.
<section data-background-transition="zoom">
function linkify( selector ) {
if( supports3DTransforms ) {
var nodes = document.querySelectorAll( selector );
for( var i = 0, len = nodes.length; i < len; i++ ) {
var node = nodes[i];
if( !node.className ) {
node.className += ' roll';
}
}
}
}
Code syntax highlighting courtesy of highlight.js.
Item | Value | Quantity |
---|---|---|
Apples | $1 | 7 |
Lemonade | $2 | 18 |
Bread | $3 | 2 |
These guys come in two forms, inline: The nice thing about standards is that there are so many to choose from
and block:
“For years there has been a theory that millions of monkeys typing at random on millions of typewriters would reproduce the entire works of Shakespeare. The Internet has proven this theory to be untrue.”
You can link between slides internally, like this.
There's a speaker view. It includes a timer, preview of the upcoming slide as well as your speaker notes.
Press the S key to try it out.
Presentations can be exported to PDF, here's an example:
Set data-state="something"
on a slide and "something"
will be added as a class to the document element when the slide is open. This lets you
apply broader style changes, like switching the page background.
Additionally custom events can be triggered on a per slide basis by binding to the data-state
name.
Reveal.addEventListener( 'customevent', function() {
console.log( '"customevent" has fired' );
} );
Press B or . on your keyboard to pause the presentation. This is helpful when you're on stage and want to take distracting slides off the screen.