Intro to Craft 3

Intro to Craft 3

A look at the new features coming in Craft CMS 3

1d2ffecbd0a4929ad92a1166b247e6a6?s=128

Brandon Kelly

April 26, 2017
Tweet

Transcript

  1. None
  2. 1. Security & Performance

  3. Modern Tech Stack — PHP 7 — Yii 2 —

    Guzzle 6 — Twig 2 — OpenSSL
  4. Average time (milliseconds) taken to load the Happy Lager homepage

    over 100 requests
  5. Seconds taken to load 5,000 entries at once

  6. Memory (MB) consumed when loading 5,000 entries at once

  7. 2. Composer

  8. Craft is now a Composer dependency right alongside other project

    dependencies.
  9. Craft is now a Composer dependency right alongside other project

    dependencies. > composer require \ craftcms/cms:^3.0.0-beta.1
  10. There’s also a Composer project you can use as a

    starting point. > composer create-project \ craftcms/craft \ my_project \ --stability beta
  11. The default project structure has changed a bit. Old New

    craft/app/ vendor/craftcms/cms/ craft/config/ config/ craft/storage/ storage/ craft/templates/ templates/ public/ web/
  12. Craft is on GitHub.

  13. Craft is on GitHub.

  14. Live on the bleeding edge. > composer require \ craftcms/cms:"dev-develop

    as 3.0.0-beta.99"
  15. 3. Multi-Site

  16. Sites are like locales, except… — you give them a

    custom name and handle — they have language, but they are not defined by it — multiple sites can share the same language — fields can be translated per-site, per-language, or even something custom
  17. When should you use Multi-Site? ! " Multi-lingual sites Different

    orgs Sister sites No shared content Landing pages
  18. 4. Internationalization

  19. Internationalization improvements in Craft 3: — Craft uses the Intl

    extension when available. — Fallback data for all the locales is available at github.com/craftcms/locales — Support for PostgreSQL ! — Translation categories
  20. 5. Assets

  21. Image Editor

  22. Image Editor

  23. None
  24. Volumes — Asset Sources are called “Volumes” now — Plugins

    can supply custom volume types — User photos are stored as assets now, and you choose which volume
  25. 6. Utilities

  26. 6. Utilities

  27. 6. Utilities

  28. 6. Utilities

  29. 6. Utilities

  30. 6. Utilities

  31. 6. Utilities

  32. 6. Utilities

  33. 6. Utilities

  34. 6. Utilities

  35. 7. Content Migrations

  36. Craft can now manage migrations that are specific to your

    project. > ./craft migrate/create create_new_field
  37. Content migrations are stored in a migrations/ folder within your

    Craft project.
  38. use craft\db\Migration; use craft\fields\PlainText; class m170331_030925_create_new_field extends Migration { public

    function safeUp() { $field = new PlainText(); $field->groupId = 1; $field->name = 'Address'; $field->handle = 'address'; $field->multiline = true; \Craft::$app->fields->saveField($field); } }
  39. Content migrations have access to the full set of Craft

    APIs, so you can do whatever you want in them.
  40. 8. Templating

  41. Element Queries

  42. ElementQuery is the new ElementCriteriaModel.

  43. ElementQuery is the new ElementCriteriaModel. Still works the same, for

    the most part. {% set entries = craft.entries() .section('news') .limit(10) %}
  44. ElementQuery is the new ElementCriteriaModel. Still works the same, for

    the most part. {% set entries = craft.entries() .section('news') .limit(10) %} But way, way more powerful.
  45. A few functions have changed. Old New find() all() first()

    one() order() orderBy() total() count()
  46. Lots of new functions have been introduced. Name Purpose select(columns)

    override the SELECT addSelect(columns) add more columns to the SELECT
  47. Lots of new functions have been introduced. Name Purpose where(condition)

    override the WHERE andWhere(condition) add an AND condition to the WHERE orWhere(condition) add an OR condition to the WHERE
  48. Lots of new functions have been introduced. Name Purpose innerJoin(table)

    add an INNER JOIN leftJoin(table) add a LEFT JOIN rightJoin(table) add a RIGHT JOIN
  49. Lots of new functions have been introduced. Name Purpose asArray()

    return raw data arrays rather than Element models indexBy(column) indexes returned values by a column’s value
  50. Lots of new functions have been introduced. Name Returns column()

    first column’s values pairs() key/value pairs scalar() first value of first column exists() if there are any results
  51. Lots of new functions have been introduced. Name Returns sum(column)

    sum value average(column) average value min(column) smallest value max(column) largest value
  52. Lots of new functions have been introduced. Name Returns batch(size)

    lazy-loaded batched results each(size) iterator for all results, but lazy-loaded in batches behind the scenes
  53. Example: get entries, indexed by their IDs {% set entriesById

    = craft.entries() .section('news') .indexBy('elements.id') .all() %}
  54. Example: get entry titles, indexed by their IDs {% set

    titlesById = craft.entries() .section('news') .select('elements.id, content.title') .pairs() %}
  55. Example: get the average value for a custom field {%

    set averageAge = craft.users() .andWhere('field_age is not null') .average('field_age') %}
  56. Example: load users in lazy-loaded batches {% for user in

    craft.users().each() %} <li>{{ user.name }}</li> {% endfor %}
  57. You can output the raw SQL query to be executed:

    {% set q = craft.entries().section('news') %} <pre>{{ q.getRawSql() }}</pre>
  58. You can output the raw SQL query to be executed:

    {% set q = craft.entries().section('news') %} <pre>{{ q.getRawSql() }}</pre> Output: SELECT `elements`.`id`, `elements`.`fieldLayoutId`, `elements`.`uid`, ...
  59. cra!.app

  60. Templates can access Craft’s application instance anywhere with craft.app.

  61. Example: access a config value {% if craft.app.config.general.devMode %} <p>Craft

    is running in Dev Mode!</p> {% endif %}
  62. Example: loop through all the sections {% set sections =

    craft.app .sections.getAllSections() %} {% for section in sections %} <li>{{ section.name }}</li> {% endfor %}
  63. 9. Debug Toolbar

  64. None
  65. None
  66. None
  67. None
  68. None
  69. None
  70. None
  71. None
  72. None
  73. None
  74. None
  75. 10. Configuration

  76. Define environment-specific variables in a .env file that doesn’t get

    committed to Git. DB_SERVER="localhost" DB_USER="homestead" DB_PASSWORD="secret" DB_DATABASE="happylager"
  77. Ways to define environment-specific settings: — Per-environment configs — PHP

    dotenv environment variables — environmentVariables
  78. Ways to define environment-specific settings: — Per-environment configs — PHP

    dotenv environment variables — environmentVariables
  79. Site URLs can be defined per-environment using the siteUrl config

    setting in config/general.php. return [ '*' => [], '.dev' => [ 'siteUrl' => 'http://site.dev', ], '.com' => [ 'siteUrl' => '//site.com', ], ], ];
  80. Volume settings can be overridden in config/volumes.php. return [ 'userPhotos'

    => [ 'path' => getenv('PHOTOS_PATH'), 'url' => getenv('PHOTOS_URL'), ], ];
  81. All plugin settings can be overridden with config files now.

  82. You can set default Guzzle settings from config/guzzle.php.

  83. return [ 'headers' => ['Foo' => 'Bar'], 'query' => ['testing'

    => '123'], 'auth' => ['username', 'password'], 'proxy' => 'tcp://localhost:80' ];
  84. You can override Craft’s core application configuration with config/app.php.

  85. return [ 'components' => [ 'mailer' => function() { $settings

    = Craft::$app->systemSettings->emailSettings; $settings->transportType = MailgunAdapter::class; $settings->transportSettings = [ 'domain' => 'foo.com', 'apiKey' => 'key-xxxxxxxxxx', ]; return MailerHelper::createMailer($settings); } ], ];
  86. Recap 1. Security & Performance 2. Composer 3. Multi-Site 4.

    Internationalization 5. Assets 6. Utilities 7. Content Migrations 8. Templating 9. Debug Toolbar 10. Configuration