Slides for “The Future of Plugin Dev” workshop given by Brandon Kelly at Peers 2015.
You can watch the full recording here: https://vimeo.com/128101264
25. • No more “C” class name prefix
• Namespaces resemble the folder
structure (PSR-4)
• No more Yii::import()
• Path aliases define the root
namespaces for the autoloader
Class name/namespace changes
27. Important path aliases to be aware of
Path Alias Server Path Root Namespace
@yii …/app/vendor/yiisoft/yii2 yii
@craft/app …/app craftapp
@craft/plugins/foo …/plugins/foo craftpluginsfoo
33. • Extend Object for classes that
don’t do anything besides
represent data (glorified arrays)
• Extend Component for
everything else
When to use which?
39. Object configuration examples
class User extends Object {
public function setAge($age) {
// ...
}
public function getAge() {
// ...
}
}
$user = new User(['age' => 21]);
42. • Base: yiidiServiceLocator
• They have sub-components
• Components accessed via magic
getters and get()
• Subcomponents are created the
first time they’re requested
Service locators
49. • Web and console applications
have controllers (no more
“console command” classes)
• Controller action routing works
the same either way
• They return the response
Controllers
51. • Request classes define the incoming
web/console request
• Response classes define the outgoing
web/console response
• The response is automatically sent at
the end of the application processing
Request vs. response
52. • Describes the HTTP request
• Method (GET, POST, etc.)
• Ajax/Pjax/Flash?
• Headers, body, parameters
• Acceptable content types/languages
• HTTP authentication
• URL, host name, URI, port, SSL
• Referrer, user agent, client IP
yiiwebRequest
59. • Defined by “onEventName()”
methods on component classes
• Attached by setting a magic
“onEventName” property
• Raised by calling raiseEvent()
within the event method
Events in Yii 1
60. Yii 1 event example
class User extends CComponent {
public function wake() {
$this->onWake(new CEvent());
}
public function onWake($ev) {
$this->raiseEvent('onWake', $ev);
}
}
$user = new User();
$user->onWake = function($ev){/*...*/};
61. • Not explicitly predefined
• Attached by calling on()
• Raised by calling trigger()
Events in Yii 2
62. Yii 2 event example
class User extends Component {
public function wake() {
$this->trigger('afterWake');
}
}
$user = new User();
$user->on('afterWake', function($ev){
// ...
});
66. • For JS and CSS resources
• They can have dependencies
• They can publish their files into
the web root when registered
• They can compile LESS, Sass,
Stylus, and CoffeeScript
Asset bundles
67. Defining an asset bundle
class AppAsset extends AssetBundle
{
public $sourcePath = '@app/assets';
public $basePath = '@web/assets';
public $depends = [
'yiiwebJqueryAsset'
];
public $css = [
'css/app.scss'
];
}
68. Registering an asset bundle
Yii::$app->view->registerAssetBundle(
'fooAppAsset'
);
70. • All SELECT queries are defined
by yiidbQuery objects
• All other queries are defined by
yiidbCommand objects
• Schema-specific SQL is always
built with QueryBuilder
DB Queries
79. • Base: yiidbActiveRecord
• Records’ ::find() methods
return ActiveQuery objects
• ActiveQuery handles the query
definition and active record
object population
Active Record
80. Active record query example
$users = User::find()
->where('age => :min', [
':min' => 21
])
->all();
82. • Yii 2 uses PHP’s Intl extension to
format dates, numbers, etc.
• Only very basic single-language
fallbacks built-in.
• Only 30% of servers have Intl
• What could go wrong?
Internationalization
84. • No more Craft namespace
• Namespaces reflect the folder
structure now
• Root namespace is craftapp
• Plugins’ root namespaces follow
the pattern craftpluginsfoo
Namespaces
85. • Craft 2: craft() returns the
CraftWebApp instance
• Craft 3: Craft::$app returns the
craftappwebApplication
instance
Accessing the Application instance
86. • Magic property names are still
available:
Craft::$app->entries
• We’ve also added getter methods
for all services:
Craft::$app->getEntries()
Accessing the Application components
87. • userSession is now user /
getUser()
• httpSession is now session /
getSession()
Application component name changes
89. • In Craft 2, routes pointed to
templates by default, and could
point to a controller action with a
special syntax
• That’s reversed in Craft 2: by
default routes point to actions
Routes and controllers
92. • Params captured by URL rules
are now passed directly to the
action’s arguments
• URL Manager’s
setRouteVariables() is now
setRouteParams()
Routes and controllers
94. • No more defineAttributes()
• Attributes must be defined as
public properties on the model
• Validation rules must be defined
in the rules() method
Model changes in Craft 3
95. Craft 2 model example
class User extends BaseModel {
protected function defineAttributes()
{
return array(
'id' => AttributeType::Number,
'age' => AttributeType::Number
);
}
}
96. Craft 3 model example
class User extends Model {
public $id;
public $age;
public function rules() {
return [
['id,age', 'number']
];
}
}
98. • No more defineAttributes()
• Column names are determined
by analyzing the table
• Validation rules must be defined
in the rules() method
• Records no longer create tables
Record changes in Craft 3
114. • Elements’ ::find() methods
return ElementQuery objects
• ElementQuery handles the query
definition and element object
population
Element Queries
115. • Element types that need custom
query parameters can extend
ElementQuery and override their
element class’ ::find() method
to return their custom element
query class
Element Queries
116. • Element queries have protected
beforePrepare() and
afterPrepare() methods that
can be overridden to support
custom parameters
Element Queries
117. Element query example
class User extends Element {
public static function find() {
return new UserQuery(
get_called_class()
);
}
// ...
}
118. Element query example
class UserQuery extends ElementQuery {
public $age;
protected function beforePrepare() {
if ($this->age) {
$this->subQuery->andWhere(
['age' => $this->age]
);
}
return parent::beforePrepare();
}
}
122. • Plugins are modules
• Primary plugin class is optional
• General plugin info now defined
in config.json
• No more strict class name/folder
requirements
Plugins
124. • Craft 2 would automatically
create/drop tables based on your
records on install/uninstall
• Craft 3 leaves it up to the plugin,
calling its install() and
uninstall() methods
Installing Plugins
125. • By default, install() and
uninstall() will check for an
“Install” migration within the
plugin, and call its safeUp() and
safeDown() methods
Installing Plugins
126. • Craft has an InstallMigration
class that can be extended
• All you have to do is override its
defineSchema() function,
defining your plugin’s default
table schema.
Installing Plugins
127. Install migration example
class Install extends InstallMigration
{
protected function defineSchema() {
'{{%foo_users}}' => [
'columns' => [
'username' => 'string(36)',
'age' => 'integer'
]
]
}
}
128. • Craft has its own Install migration
that the installer runs:
craft/app/migrations/Install.php
• Also shows how to add default
content to the tables
Installing Plugins