SlideShare ist ein Scribd-Unternehmen logo
1 von 52
CakePHP Workshop
Build fast, grow solid.
Walther Lalk
CakePHP core team member
Croogo core team member
Lead Software Developer at
Troop Scouter at 9th Pretoria
(Irene) Air Scouts
Husband
Development environment
VirtualBox withVagrant
Recommended vagrant box is the FriendsOfCake
vagrant box.
Download it by running
$ git clone https://github.com/FriendsOfCake/vagrant-chef.git
Then start the vagrant box up with
$ cd vagrant-chef
$ vagrant up
$ vagrant ssh (For windows you’ll probably need
to use Putty)
Add this to your hosts file
192.168.13.37 app.dev
Linux or OSX : /etc/hosts
Windows:
C:WindowsSystem32driversetchosts
PHP built in server
Ensure you have PHP 5.5.9+ with the Intl and
Mbstring and a database server running (with
the corresponding PDO extension).
Supported:
MySQL,
PostgreSQL,
SQLite,
SQL Server
I will be using this with SQLite.
Following along at home
https://github.com/dakota/phpsa2016-complete
Installing CakePHP
Run
$ composer create-project cakephp/app app
Then
$ cd app
If you are using the vagrant
box, then visit http://app.dev in
your browser.
Otherwise, wait for the next slide
PHP Server
Run
$ bin/cake server
Visit http://localhost:8765/
Getting baked
Database configuration
If you’re using the Vagrant box, and have a green tick for database, then you’re good to go.
PHP Server users probably need to do some config. Recommend simply using SQLite (It’s the easiest
to get going).
Open config/app.php
Find the Datasources, replace the default datasource with
'default' => [
'className' => 'CakeDatabaseConnection',
'driver' => 'CakeDatabaseDriverSqlite',
'database' => ROOT . DS . 'database.sqlite',
'encoding' => 'utf8',
'cacheMetadata' => true,
'quoteIdentifiers' => false,
],
Bake a database
$ bin/cake bake migration CreateMembers first_name:string last_name:string email:string
created modified
$ bin/cake bake migration CreateEvents title:string description:text start:datetime
end:datetime created modified
$ bin/cake bake migration CreateEventsMembers event_id:integer:primary
member_id:integer:primary
Bake a database
The migration bake task can sometimes get confused with composite primary keys, and tries to
make each primary key an autoincrement field. We need to fix that!
Open config/Migrations/…_CreateEventsMembers.php and remove the two
‘autoIncrement’ => true, lines.
If you are using SQLite, you need to open all the files in the config/Migrations, and change all
instances of ‘default’ => null to be ‘default’ => ‘’
Seed that database
$ bin/cake bake seed Members
Open config/Seeds/MembersSeed.php, and update the $data variable
$data = [
[
'first_name' => 'Walther',
'last_name' => 'Lalk',
'email' => 'waltherlalk@cakephp.org',
'created' => date('Y-m-d H:i:s'),
'modified' => date('Y-m-d H:i:s'),
]
];
Seed that database
$ bin/cake bake seed Events
Open config/Seeds/EventsSeed.php, and update the $data variable
$data = [
[
'title' => 'PHP South Africa 2016',
'description' => '',
'start' => '2016-09-28 08:00',
'end' => '2016-09-30 17:00',
'created' => date('Y-m-d H:i:s'),
'modified' => date('Y-m-d H:i:s'),
]
];
Running migrations
$ bin/cake migrations migrate
$ bin/cake migrations seed
Bake your application
$ bin/cake bake all Members
$ bin/cake bake all Events
Visit /members in your browser, there should be 1 member. Add another one.
Now visit /events in your browser, there should be 1 event. Add another one.
Notice how both of them have a multi-select box for members or events? We’re going to remove
that at a later stage and change how it works.
Anatomy of a CakePHP
application
Marshalling
Persisting
Validation
Open src/Model/Table/EventsTable.php, find in the validationDefault method.
Change notEmpty() to be allowEmpty()
$validator
->requirePresence('description', 'create')
->notEmpty('description');
Application rules
public function buildRules(RulesChecker $rules)
{
$rules->add(
function (Event $event) {
return $event->start <= $event->end;
},
'endAfterStart',
[
'errorField' => 'end',
'message' => 'The event cannot end before it has started'
]
);
return parent::buildRules($rules);
}
The art of knowing who’s
there
Adding a password
$ bin/cake bake migration AddPasswordToMembers password:string[60]
$ bin/cake migrations migrate
Add to src/Model/Entity/MemberEntity.php
protected function _setPassword($password)
{
if (strlen($password) > 0) {
return (new CakeAuthDefaultPasswordHasher())->hash($password);
}
return $this->password;
}
Adding a password
Add to src/Templates/Members/add.ctp and src/Templates/Members/edit.ctp
echo $this->Form->input('password', [
'value' => ''
]);
echo $this->Form->input('password_confirm', [
'label' => 'Confirm password',
’type' => 'password',
'value' => ''
]);
Adding a password
Add validation to the password, and password confirmation fields.
$validator
->requirePresence('password', 'create')
->notEmpty('password', 'You need to provide a password.', 'create')
->minLength('password', 6, 'Your password must be 6 characters or longer');
$condition = function ($context) {
return !empty($context['data']['password']);
};
$validator
->requirePresence('password_confirm', $condition)
->notEmpty('password_confirm', 'Please confirm your password', $condition)
->add('password_confirm', 'mustMatch', [
'rule' => function ($check, $context) {
return $context['data']['password'] === $check;
},
'on' => $condition,
'message' => 'Password does not match'
]);
Adding a password
Edit your existing members and give them passwords. They will be automatically hashed.
Creating the login action
Open src/Controller/MembersController.php
public function login()
{
if ($this->request->is('post')) {
$member = $this->Auth->identify();
if ($member) {
$this->Auth->setUser($member);
return $this->redirect($this->Auth->redirectUrl());
} else {
$this->Flash->error(__('Email address or password is incorrect'), [
'key' => 'auth'
]);
}
}
}
public function logout()
{
return $this->redirect($this->Auth->logout());
}
Creating the login template
Create src/Templates/Members/login.ctp
<div class="login form large-12 columns content">
<?php
echo $this->Form->create();
echo $this->Form->input('email');
echo $this->Form->input('password');
echo $this->Form->button('Login');
echo $this->Form->end();
?>
</div>
Enabling Authentication
Open src/Controller/AppController.php, and add to the initialize method.
$this->loadComponent('Auth', [
'loginAction' => [
'controller' => 'Members',
'action' => 'login',
],
'authenticate' => [
'Form' => [
'fields' => ['username' => 'email', 'password' => 'password'],
'userModel' => 'Members'
]
]
]);
Try to visit /members now
Event security
We are adding a organiser to our events. Only the organiser is allowed to change the event.
$ bin/cake bake migration AddOrganiserToEvents organiser_id:integer
$ bin/cake migrations migrate
$this->belongsTo('Organiser', [
'foreignKey' => 'organiser_id',
'className' => 'Members'
]);
Open src/Model/Table/EventsTable.php, and add to the initialize method.
Open src/Model/Table/MembersTable.php, and add to the initialize method.
$this->hasMany('OrganisingEvents', [
'foreignKey' => 'organiser_id',
'className' => 'Events'
]);
Event security
Enforce foreign key constraints at an application level by adding the following to the buildRules
method in the EventsTable class.
$rules->existsIn('organiser_id', 'Organiser', 'That member does not exist in the database.');
Who’s the organiser?
The member creating the event should be able to choose who the event organiser is.
In src/Templates/Events/add.ctp
echo $this->Form->input('organiser_id', [
'empty' => '-- Select organiser --',
'options' => $members,
'default' => $this->request->session()->read('Auth.User.id')
]);
In src/Templates/Events/edit.ctp
echo $this->Form->input('organiser_id', [
'empty' => '-- Select organiser --',
'options' => $members,
]);
Who’s that?
Who is organiser 1?
protected $_virtual = [
'full_name'
];
protected function _getFullName()
{
return sprintf('%s %s (%s)', $this->first_name, $this->last_name, $this->email);
}
Add to the Member entity class
In the MembersTable class, change the displayField to ‘full_name’
Better!
Event security
To enforce that an event can only be modified by it’s organiser, open
src/Controller/EventsController.php and add to the edit method, just after the get() call.
if ($event->organiser_id !== $this->Auth->user('id')) {
throw new ForbiddenException();
}
Member security
To prevent a member from editing another member’s profile, simply add
if ($id !== $this->Auth->user('id')) {
throw new ForbiddenException();
}
To the edit method in the MembersController.
Allow registrations
Allow new members to register by adding a beforeFilter method to the MembersController.
public function beforeFilter(CakeEventEvent $event)
{
$this->Auth->allow('add');
return parent::beforeFilter($event);
}
Add make a pretty URL for registration and login. Add to config/routes.php
$routes->connect('/register', ['controller' => 'Members', 'action' => 'add']);
$routes->connect('/login', ['controller' => 'Members', 'action' => 'login']);
I’m going
Belongs to many
Create a join table object
$ bin/cake bake model EventsMembers
Change
'joinTable' => 'events_members'
to
'through' => 'EventsMembers',
'saveStrategy' => CakeORMAssociationBelongsToMany::SAVE_APPEND
in the Members and Events table objects.
Event attendance
Add a field to capture the type of event attendance
$ bin/cake bake migration AddTypeToEventsMembers type:string[10]
$ bin/cake migrations migrate
Add to EventsMember entity
const TYPE_GOING = 'going';
const TYPE_INTERESTED = 'interested';
const TYPE_NOT_GOING = 'notGoing';
Event attendance
In EventsTable, add
public function linkMember(AppModelEntityEvent $event, $memberId, $type)
{
$member = $this->Members->get($memberId);
//Add the join data
$member->_joinData = new AppModelEntityEventsMember([
'type' => $type
]);
return $this->association('Members')->link($event, [$member]);
}
Event attendance
In EventsController, add
public function linkActiveMember($eventId, $type)
{
$event = $this->Events->get($eventId);
if ($this->Events->linkMember($event, $this->Auth->user('id'), $type)) {
$this->Flash->success('Registered!');
} else {
$this->Flash->error('Something went wrong.');
}
return $this->redirect($this->referer());
}
Event attendance
In the Event entity
public function memberStatus($memberId, $type)
{
if (!$this->has('members')) {
return false;
}
$member = collection($this->members)
->firstMatch(['id' => $memberId]);
if (!$member) {
return false;
}
return $member->_joinData->type === $type;
}
Event attendance
In src/Template/Events/index.ctp, in the actions table cell
<br>
<?php
if (!$event->memberStatus($this->request->session()
->read('Auth.User.id'), AppModelEntityEventsMember::TYPE_GOING)
) {
echo $this->Html->link(__('Going'), [
'action' => 'linkActiveMember',
$event->id,
AppModelEntityEventsMember::TYPE_GOING
]);
}
if (!$event->memberStatus($this->request->session()
->read('Auth.User.id'), AppModelEntityEventsMember::TYPE_INTERESTED)
) {
echo $this->Html->link(__('Interested'), [
'action' => 'linkActiveMember',
$event->id,
AppModelEntityEventsMember::TYPE_INTERESTED
]);
}
if (!$event->memberStatus($this->request->session()
->read('Auth.User.id'), AppModelEntityEventsMember::TYPE_NOT_GOING)
) {
echo $this->Html->link(__('Not going'), [
'action' => 'linkActiveMember',
$event->id,
AppModelEntityEventsMember::TYPE_NOT_GOING
]);
}
?>
Event attendance
Open src/Templates/Events/add.ctp and src/Templates/Events/edit.ctp and remove
echo $this->Form->input('members._ids', ['options' => $members]);
Open src/Templates/Members/add.ctp and src/Templates/Members/edit.ctp and remove
echo $this->Form->input('events._ids', ['options' => $events]);
We don’t need code where
we’re going
Installing CRUD
$ composer require friendsofcake/crud
$ bin/cake plugin load Crud
use CrudControllerControllerTrait;
Add the Crud trait to your AppController
And, load the Crud component in the initialize method
$this->loadComponent('Crud.Crud', [
'actions' => [
'Crud.Index',
'Crud.View',
'Crud.Edit',
'Crud.Add',
'Crud.Delete'
],
'listeners' => [
'Crud.RelatedModels'
]
]);
Remove all your code
Or, at least all index, view, edit, add and delete actions.
It still works!?
Thanks to the power of CRUD, everything still works
(Mostly)
Adding back functionality
Create a AuthListener class in the src/Listener directory
<?php
namespace AppListener;
use CakeEventEvent;
use CakeNetworkExceptionForbiddenException;
use CrudListenerBaseListener;
/**
* Class AuthListener
*/
class AuthListener extends BaseListener
{
/**
* Settings
*
* @var array
*/
protected $_defaultConfig = [
'property' => 'id',
'message' => 'You are not allowed to access the requested resource.',
'actions' => ['edit', 'delete']
];
Adding back functionality
public function afterFind(Event $event)
{
if (!in_array($this->_request()->param('action'), $this->config('actions'))
) {
return;
}
$entity = $event->subject()->entity;
$userId = $this->_controller()->Auth->user('id');
if ($entity->get($this->config('property')) !== $userId) {
throw new ForbiddenException($this->config('message'));
}
}
}
Adding back functionality
MembersController beforeFilter, add:
$this->Crud->addListener('Auth', 'Auth', [
'property' => 'id'
]);
Add a beforeFilter for EventsController
public function beforeFilter(CakeEventEvent $event)
{
$this->Crud->addListener('Auth', 'Auth', [
'property' => 'organiser_id'
]);
return parent::beforeFilter($event);
}
Questions?
Thank You.

Weitere ähnliche Inhalte

Was ist angesagt?

PHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the testsPHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the testsMichelangelo van Dam
 
PHPunit and you
PHPunit and youPHPunit and you
PHPunit and youmarkstory
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design PatternsHugo Hamon
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistenceHugo Hamon
 
PHP tips and tricks
PHP tips and tricks PHP tips and tricks
PHP tips and tricks Damien Seguy
 
Things I Believe Now That I'm Old
Things I Believe Now That I'm OldThings I Believe Now That I'm Old
Things I Believe Now That I'm OldRoss Tuck
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICKonstantin Kudryashov
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleHugo Hamon
 
PHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くためにPHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くためにYuya Takeyama
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConRafael Dohms
 
R57shell
R57shellR57shell
R57shellady36
 
Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB jhchabran
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonfRafael Dohms
 
Your code sucks, let's fix it
Your code sucks, let's fix itYour code sucks, let's fix it
Your code sucks, let's fix itRafael Dohms
 
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011Masahiro Nagano
 
The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016Kacper Gunia
 

Was ist angesagt? (20)

PHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the testsPHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the tests
 
PHPunit and you
PHPunit and youPHPunit and you
PHPunit and you
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design Patterns
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistence
 
PHP tips and tricks
PHP tips and tricks PHP tips and tricks
PHP tips and tricks
 
Agile database access with CakePHP 3
Agile database access with CakePHP 3Agile database access with CakePHP 3
Agile database access with CakePHP 3
 
Things I Believe Now That I'm Old
Things I Believe Now That I'm OldThings I Believe Now That I'm Old
Things I Believe Now That I'm Old
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
 
Separation of concerns - DPC12
Separation of concerns - DPC12Separation of concerns - DPC12
Separation of concerns - DPC12
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et Pimple
 
PHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くためにPHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くために
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnCon
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
 
R57shell
R57shellR57shell
R57shell
 
Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
 
Your code sucks, let's fix it
Your code sucks, let's fix itYour code sucks, let's fix it
Your code sucks, let's fix it
 
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
 
The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
 

Andere mochten auch

An Amazing Grizzly
An Amazing GrizzlyAn Amazing Grizzly
An Amazing GrizzlyJoke Channel
 
Wordpress.comで制作する時のちょっとしたこと
Wordpress.comで制作する時のちょっとしたことWordpress.comで制作する時のちょっとしたこと
Wordpress.comで制作する時のちょっとしたことFLOW web planning & design
 
Rok na vsi 2008
Rok na vsi  2008Rok na vsi  2008
Rok na vsi 2008jannaa
 
Премиум клуб эротического массажа
Премиум клуб эротического массажаПремиум клуб эротического массажа
Премиум клуб эротического массажаIngenium Бизнес
 
Weekly, The Innovation Startup
Weekly, The Innovation StartupWeekly, The Innovation Startup
Weekly, The Innovation StartupGo Weekly
 
How I built web services in CakePHP
How I built web services in CakePHPHow I built web services in CakePHP
How I built web services in CakePHPDavid Yell
 
ソーシャルビジネス勉強会 Vol.10 ファシリテーショングラフィック
ソーシャルビジネス勉強会 Vol.10 ファシリテーショングラフィックソーシャルビジネス勉強会 Vol.10 ファシリテーショングラフィック
ソーシャルビジネス勉強会 Vol.10 ファシリテーショングラフィックTomoharu Ishibashi
 
Type Safe Assets Handling in Swift
Type Safe Assets Handling in SwiftType Safe Assets Handling in Swift
Type Safe Assets Handling in SwiftKazunobu Tasaka
 
Project parivartan transformation of sbi
Project parivartan  transformation of sbiProject parivartan  transformation of sbi
Project parivartan transformation of sbiRajnish Deo
 
Swiftで説明する「モナド」:Swiftにおける関数型プログラミングの使い方
Swiftで説明する「モナド」:Swiftにおける関数型プログラミングの使い方Swiftで説明する「モナド」:Swiftにおける関数型プログラミングの使い方
Swiftで説明する「モナド」:Swiftにおける関数型プログラミングの使い方Roy Kim
 
Константин Карпалов — «Cash rules everything around me, или как заработать ми...
Константин Карпалов — «Cash rules everything around me, или как заработать ми...Константин Карпалов — «Cash rules everything around me, или как заработать ми...
Константин Карпалов — «Cash rules everything around me, или как заработать ми...shevchuk_conf
 
DEVALUATION OF INDIAN CURRENCY
DEVALUATION OF INDIAN CURRENCYDEVALUATION OF INDIAN CURRENCY
DEVALUATION OF INDIAN CURRENCYSheetal Priya
 
Was jeder Java-Entwickler über Strings wissen sollte
Was jeder Java-Entwickler über Strings wissen sollteWas jeder Java-Entwickler über Strings wissen sollte
Was jeder Java-Entwickler über Strings wissen sollteberndmueller
 
WordPress テーマ Habakiri と公式ディレクトリへのテーマ登録
WordPress テーマ Habakiri と公式ディレクトリへのテーマ登録WordPress テーマ Habakiri と公式ディレクトリへのテーマ登録
WordPress テーマ Habakiri と公式ディレクトリへのテーマ登録タカシ キタジマ
 
Entrepreneurship development programme notes
Entrepreneurship development programme notes Entrepreneurship development programme notes
Entrepreneurship development programme notes Sonam kapil
 
Anchal presentation on banking industry
Anchal presentation on banking industryAnchal presentation on banking industry
Anchal presentation on banking industrymemymyself
 

Andere mochten auch (20)

An Amazing Grizzly
An Amazing GrizzlyAn Amazing Grizzly
An Amazing Grizzly
 
Wordpress.comで制作する時のちょっとしたこと
Wordpress.comで制作する時のちょっとしたことWordpress.comで制作する時のちょっとしたこと
Wordpress.comで制作する時のちょっとしたこと
 
E05842831
E05842831E05842831
E05842831
 
Rok na vsi 2008
Rok na vsi  2008Rok na vsi  2008
Rok na vsi 2008
 
Премиум клуб эротического массажа
Премиум клуб эротического массажаПремиум клуб эротического массажа
Премиум клуб эротического массажа
 
Weekly, The Innovation Startup
Weekly, The Innovation StartupWeekly, The Innovation Startup
Weekly, The Innovation Startup
 
How I built web services in CakePHP
How I built web services in CakePHPHow I built web services in CakePHP
How I built web services in CakePHP
 
ソーシャルビジネス勉強会 Vol.10 ファシリテーショングラフィック
ソーシャルビジネス勉強会 Vol.10 ファシリテーショングラフィックソーシャルビジネス勉強会 Vol.10 ファシリテーショングラフィック
ソーシャルビジネス勉強会 Vol.10 ファシリテーショングラフィック
 
Type Safe Assets Handling in Swift
Type Safe Assets Handling in SwiftType Safe Assets Handling in Swift
Type Safe Assets Handling in Swift
 
Objective-C Generics
Objective-C GenericsObjective-C Generics
Objective-C Generics
 
Project parivartan transformation of sbi
Project parivartan  transformation of sbiProject parivartan  transformation of sbi
Project parivartan transformation of sbi
 
C05921721
C05921721C05921721
C05921721
 
Swiftで説明する「モナド」:Swiftにおける関数型プログラミングの使い方
Swiftで説明する「モナド」:Swiftにおける関数型プログラミングの使い方Swiftで説明する「モナド」:Swiftにおける関数型プログラミングの使い方
Swiftで説明する「モナド」:Swiftにおける関数型プログラミングの使い方
 
Константин Карпалов — «Cash rules everything around me, или как заработать ми...
Константин Карпалов — «Cash rules everything around me, или как заработать ми...Константин Карпалов — «Cash rules everything around me, или как заработать ми...
Константин Карпалов — «Cash rules everything around me, или как заработать ми...
 
DEVALUATION OF INDIAN CURRENCY
DEVALUATION OF INDIAN CURRENCYDEVALUATION OF INDIAN CURRENCY
DEVALUATION OF INDIAN CURRENCY
 
Was jeder Java-Entwickler über Strings wissen sollte
Was jeder Java-Entwickler über Strings wissen sollteWas jeder Java-Entwickler über Strings wissen sollte
Was jeder Java-Entwickler über Strings wissen sollte
 
Campos de una trama
Campos de una tramaCampos de una trama
Campos de una trama
 
WordPress テーマ Habakiri と公式ディレクトリへのテーマ登録
WordPress テーマ Habakiri と公式ディレクトリへのテーマ登録WordPress テーマ Habakiri と公式ディレクトリへのテーマ登録
WordPress テーマ Habakiri と公式ディレクトリへのテーマ登録
 
Entrepreneurship development programme notes
Entrepreneurship development programme notes Entrepreneurship development programme notes
Entrepreneurship development programme notes
 
Anchal presentation on banking industry
Anchal presentation on banking industryAnchal presentation on banking industry
Anchal presentation on banking industry
 

Ähnlich wie CakePHP workshop

The Zen of Lithium
The Zen of LithiumThe Zen of Lithium
The Zen of LithiumNate Abele
 
WordPress as an application framework
WordPress as an application frameworkWordPress as an application framework
WordPress as an application frameworkDustin Filippini
 
Virtual Madness @ Etsy
Virtual Madness @ EtsyVirtual Madness @ Etsy
Virtual Madness @ EtsyNishan Subedi
 
laravel tricks in 50minutes
laravel tricks in 50minuteslaravel tricks in 50minutes
laravel tricks in 50minutesBarang CK
 
50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 MinutesAzim Kurt
 
Bag Of Tricks From Iusethis
Bag Of Tricks From IusethisBag Of Tricks From Iusethis
Bag Of Tricks From IusethisMarcus Ramberg
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsMichael Peacock
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
Perl web app 테스트전략
Perl web app 테스트전략Perl web app 테스트전략
Perl web app 테스트전략Jeen Lee
 
Unit 3 - for php application Sessions.pptx
Unit 3  -  for php  application Sessions.pptxUnit 3  -  for php  application Sessions.pptx
Unit 3 - for php application Sessions.pptxmythili213835
 
Apostrophe (improved Paris edition)
Apostrophe (improved Paris edition)Apostrophe (improved Paris edition)
Apostrophe (improved Paris edition)tompunk
 
What mom never told you about bundle configurations - Symfony Live Paris 2012
What mom never told you about bundle configurations - Symfony Live Paris 2012What mom never told you about bundle configurations - Symfony Live Paris 2012
What mom never told you about bundle configurations - Symfony Live Paris 2012D
 
Api Design
Api DesignApi Design
Api Designsartak
 

Ähnlich wie CakePHP workshop (20)

The Zen of Lithium
The Zen of LithiumThe Zen of Lithium
The Zen of Lithium
 
WordPress as an application framework
WordPress as an application frameworkWordPress as an application framework
WordPress as an application framework
 
Virtual Madness @ Etsy
Virtual Madness @ EtsyVirtual Madness @ Etsy
Virtual Madness @ Etsy
 
Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010
 
laravel tricks in 50minutes
laravel tricks in 50minuteslaravel tricks in 50minutes
laravel tricks in 50minutes
 
50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
 
QA for PHP projects
QA for PHP projectsQA for PHP projects
QA for PHP projects
 
Bag Of Tricks From Iusethis
Bag Of Tricks From IusethisBag Of Tricks From Iusethis
Bag Of Tricks From Iusethis
 
Daily notes
Daily notesDaily notes
Daily notes
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friends
 
Mojolicious
MojoliciousMojolicious
Mojolicious
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Perl web app 테스트전략
Perl web app 테스트전략Perl web app 테스트전략
Perl web app 테스트전략
 
Unit 3 - for php application Sessions.pptx
Unit 3  -  for php  application Sessions.pptxUnit 3  -  for php  application Sessions.pptx
Unit 3 - for php application Sessions.pptx
 
PhpBB meets Symfony2
PhpBB meets Symfony2PhpBB meets Symfony2
PhpBB meets Symfony2
 
Apostrophe (improved Paris edition)
Apostrophe (improved Paris edition)Apostrophe (improved Paris edition)
Apostrophe (improved Paris edition)
 
What mom never told you about bundle configurations - Symfony Live Paris 2012
What mom never told you about bundle configurations - Symfony Live Paris 2012What mom never told you about bundle configurations - Symfony Live Paris 2012
What mom never told you about bundle configurations - Symfony Live Paris 2012
 
Api Design
Api DesignApi Design
Api Design
 

Kürzlich hochgeladen

Towards a code of practice for AI in AT.pptx
Towards a code of practice for AI in AT.pptxTowards a code of practice for AI in AT.pptx
Towards a code of practice for AI in AT.pptxJisc
 
Application orientated numerical on hev.ppt
Application orientated numerical on hev.pptApplication orientated numerical on hev.ppt
Application orientated numerical on hev.pptRamjanShidvankar
 
General Principles of Intellectual Property: Concepts of Intellectual Proper...
General Principles of Intellectual Property: Concepts of Intellectual  Proper...General Principles of Intellectual Property: Concepts of Intellectual  Proper...
General Principles of Intellectual Property: Concepts of Intellectual Proper...Poonam Aher Patil
 
2024-NATIONAL-LEARNING-CAMP-AND-OTHER.pptx
2024-NATIONAL-LEARNING-CAMP-AND-OTHER.pptx2024-NATIONAL-LEARNING-CAMP-AND-OTHER.pptx
2024-NATIONAL-LEARNING-CAMP-AND-OTHER.pptxMaritesTamaniVerdade
 
Interdisciplinary_Insights_Data_Collection_Methods.pptx
Interdisciplinary_Insights_Data_Collection_Methods.pptxInterdisciplinary_Insights_Data_Collection_Methods.pptx
Interdisciplinary_Insights_Data_Collection_Methods.pptxPooja Bhuva
 
NO1 Top Black Magic Specialist In Lahore Black magic In Pakistan Kala Ilam Ex...
NO1 Top Black Magic Specialist In Lahore Black magic In Pakistan Kala Ilam Ex...NO1 Top Black Magic Specialist In Lahore Black magic In Pakistan Kala Ilam Ex...
NO1 Top Black Magic Specialist In Lahore Black magic In Pakistan Kala Ilam Ex...Amil baba
 
How to Give a Domain for a Field in Odoo 17
How to Give a Domain for a Field in Odoo 17How to Give a Domain for a Field in Odoo 17
How to Give a Domain for a Field in Odoo 17Celine George
 
Unit 3 Emotional Intelligence and Spiritual Intelligence.pdf
Unit 3 Emotional Intelligence and Spiritual Intelligence.pdfUnit 3 Emotional Intelligence and Spiritual Intelligence.pdf
Unit 3 Emotional Intelligence and Spiritual Intelligence.pdfDr Vijay Vishwakarma
 
Basic Civil Engineering first year Notes- Chapter 4 Building.pptx
Basic Civil Engineering first year Notes- Chapter 4 Building.pptxBasic Civil Engineering first year Notes- Chapter 4 Building.pptx
Basic Civil Engineering first year Notes- Chapter 4 Building.pptxDenish Jangid
 
Exploring_the_Narrative_Style_of_Amitav_Ghoshs_Gun_Island.pptx
Exploring_the_Narrative_Style_of_Amitav_Ghoshs_Gun_Island.pptxExploring_the_Narrative_Style_of_Amitav_Ghoshs_Gun_Island.pptx
Exploring_the_Narrative_Style_of_Amitav_Ghoshs_Gun_Island.pptxPooja Bhuva
 
80 ĐỀ THI THỬ TUYỂN SINH TIẾNG ANH VÀO 10 SỞ GD – ĐT THÀNH PHỐ HỒ CHÍ MINH NĂ...
80 ĐỀ THI THỬ TUYỂN SINH TIẾNG ANH VÀO 10 SỞ GD – ĐT THÀNH PHỐ HỒ CHÍ MINH NĂ...80 ĐỀ THI THỬ TUYỂN SINH TIẾNG ANH VÀO 10 SỞ GD – ĐT THÀNH PHỐ HỒ CHÍ MINH NĂ...
80 ĐỀ THI THỬ TUYỂN SINH TIẾNG ANH VÀO 10 SỞ GD – ĐT THÀNH PHỐ HỒ CHÍ MINH NĂ...Nguyen Thanh Tu Collection
 
How to Manage Global Discount in Odoo 17 POS
How to Manage Global Discount in Odoo 17 POSHow to Manage Global Discount in Odoo 17 POS
How to Manage Global Discount in Odoo 17 POSCeline George
 
ICT role in 21st century education and it's challenges.
ICT role in 21st century education and it's challenges.ICT role in 21st century education and it's challenges.
ICT role in 21st century education and it's challenges.MaryamAhmad92
 
Kodo Millet PPT made by Ghanshyam bairwa college of Agriculture kumher bhara...
Kodo Millet  PPT made by Ghanshyam bairwa college of Agriculture kumher bhara...Kodo Millet  PPT made by Ghanshyam bairwa college of Agriculture kumher bhara...
Kodo Millet PPT made by Ghanshyam bairwa college of Agriculture kumher bhara...pradhanghanshyam7136
 
On National Teacher Day, meet the 2024-25 Kenan Fellows
On National Teacher Day, meet the 2024-25 Kenan FellowsOn National Teacher Day, meet the 2024-25 Kenan Fellows
On National Teacher Day, meet the 2024-25 Kenan FellowsMebane Rash
 
Salient Features of India constitution especially power and functions
Salient Features of India constitution especially power and functionsSalient Features of India constitution especially power and functions
Salient Features of India constitution especially power and functionsKarakKing
 
Sensory_Experience_and_Emotional_Resonance_in_Gabriel_Okaras_The_Piano_and_Th...
Sensory_Experience_and_Emotional_Resonance_in_Gabriel_Okaras_The_Piano_and_Th...Sensory_Experience_and_Emotional_Resonance_in_Gabriel_Okaras_The_Piano_and_Th...
Sensory_Experience_and_Emotional_Resonance_in_Gabriel_Okaras_The_Piano_and_Th...Pooja Bhuva
 
Python Notes for mca i year students osmania university.docx
Python Notes for mca i year students osmania university.docxPython Notes for mca i year students osmania university.docx
Python Notes for mca i year students osmania university.docxRamakrishna Reddy Bijjam
 
Graduate Outcomes Presentation Slides - English
Graduate Outcomes Presentation Slides - EnglishGraduate Outcomes Presentation Slides - English
Graduate Outcomes Presentation Slides - Englishneillewis46
 

Kürzlich hochgeladen (20)

Towards a code of practice for AI in AT.pptx
Towards a code of practice for AI in AT.pptxTowards a code of practice for AI in AT.pptx
Towards a code of practice for AI in AT.pptx
 
Application orientated numerical on hev.ppt
Application orientated numerical on hev.pptApplication orientated numerical on hev.ppt
Application orientated numerical on hev.ppt
 
General Principles of Intellectual Property: Concepts of Intellectual Proper...
General Principles of Intellectual Property: Concepts of Intellectual  Proper...General Principles of Intellectual Property: Concepts of Intellectual  Proper...
General Principles of Intellectual Property: Concepts of Intellectual Proper...
 
2024-NATIONAL-LEARNING-CAMP-AND-OTHER.pptx
2024-NATIONAL-LEARNING-CAMP-AND-OTHER.pptx2024-NATIONAL-LEARNING-CAMP-AND-OTHER.pptx
2024-NATIONAL-LEARNING-CAMP-AND-OTHER.pptx
 
Interdisciplinary_Insights_Data_Collection_Methods.pptx
Interdisciplinary_Insights_Data_Collection_Methods.pptxInterdisciplinary_Insights_Data_Collection_Methods.pptx
Interdisciplinary_Insights_Data_Collection_Methods.pptx
 
NO1 Top Black Magic Specialist In Lahore Black magic In Pakistan Kala Ilam Ex...
NO1 Top Black Magic Specialist In Lahore Black magic In Pakistan Kala Ilam Ex...NO1 Top Black Magic Specialist In Lahore Black magic In Pakistan Kala Ilam Ex...
NO1 Top Black Magic Specialist In Lahore Black magic In Pakistan Kala Ilam Ex...
 
Mehran University Newsletter Vol-X, Issue-I, 2024
Mehran University Newsletter Vol-X, Issue-I, 2024Mehran University Newsletter Vol-X, Issue-I, 2024
Mehran University Newsletter Vol-X, Issue-I, 2024
 
How to Give a Domain for a Field in Odoo 17
How to Give a Domain for a Field in Odoo 17How to Give a Domain for a Field in Odoo 17
How to Give a Domain for a Field in Odoo 17
 
Unit 3 Emotional Intelligence and Spiritual Intelligence.pdf
Unit 3 Emotional Intelligence and Spiritual Intelligence.pdfUnit 3 Emotional Intelligence and Spiritual Intelligence.pdf
Unit 3 Emotional Intelligence and Spiritual Intelligence.pdf
 
Basic Civil Engineering first year Notes- Chapter 4 Building.pptx
Basic Civil Engineering first year Notes- Chapter 4 Building.pptxBasic Civil Engineering first year Notes- Chapter 4 Building.pptx
Basic Civil Engineering first year Notes- Chapter 4 Building.pptx
 
Exploring_the_Narrative_Style_of_Amitav_Ghoshs_Gun_Island.pptx
Exploring_the_Narrative_Style_of_Amitav_Ghoshs_Gun_Island.pptxExploring_the_Narrative_Style_of_Amitav_Ghoshs_Gun_Island.pptx
Exploring_the_Narrative_Style_of_Amitav_Ghoshs_Gun_Island.pptx
 
80 ĐỀ THI THỬ TUYỂN SINH TIẾNG ANH VÀO 10 SỞ GD – ĐT THÀNH PHỐ HỒ CHÍ MINH NĂ...
80 ĐỀ THI THỬ TUYỂN SINH TIẾNG ANH VÀO 10 SỞ GD – ĐT THÀNH PHỐ HỒ CHÍ MINH NĂ...80 ĐỀ THI THỬ TUYỂN SINH TIẾNG ANH VÀO 10 SỞ GD – ĐT THÀNH PHỐ HỒ CHÍ MINH NĂ...
80 ĐỀ THI THỬ TUYỂN SINH TIẾNG ANH VÀO 10 SỞ GD – ĐT THÀNH PHỐ HỒ CHÍ MINH NĂ...
 
How to Manage Global Discount in Odoo 17 POS
How to Manage Global Discount in Odoo 17 POSHow to Manage Global Discount in Odoo 17 POS
How to Manage Global Discount in Odoo 17 POS
 
ICT role in 21st century education and it's challenges.
ICT role in 21st century education and it's challenges.ICT role in 21st century education and it's challenges.
ICT role in 21st century education and it's challenges.
 
Kodo Millet PPT made by Ghanshyam bairwa college of Agriculture kumher bhara...
Kodo Millet  PPT made by Ghanshyam bairwa college of Agriculture kumher bhara...Kodo Millet  PPT made by Ghanshyam bairwa college of Agriculture kumher bhara...
Kodo Millet PPT made by Ghanshyam bairwa college of Agriculture kumher bhara...
 
On National Teacher Day, meet the 2024-25 Kenan Fellows
On National Teacher Day, meet the 2024-25 Kenan FellowsOn National Teacher Day, meet the 2024-25 Kenan Fellows
On National Teacher Day, meet the 2024-25 Kenan Fellows
 
Salient Features of India constitution especially power and functions
Salient Features of India constitution especially power and functionsSalient Features of India constitution especially power and functions
Salient Features of India constitution especially power and functions
 
Sensory_Experience_and_Emotional_Resonance_in_Gabriel_Okaras_The_Piano_and_Th...
Sensory_Experience_and_Emotional_Resonance_in_Gabriel_Okaras_The_Piano_and_Th...Sensory_Experience_and_Emotional_Resonance_in_Gabriel_Okaras_The_Piano_and_Th...
Sensory_Experience_and_Emotional_Resonance_in_Gabriel_Okaras_The_Piano_and_Th...
 
Python Notes for mca i year students osmania university.docx
Python Notes for mca i year students osmania university.docxPython Notes for mca i year students osmania university.docx
Python Notes for mca i year students osmania university.docx
 
Graduate Outcomes Presentation Slides - English
Graduate Outcomes Presentation Slides - EnglishGraduate Outcomes Presentation Slides - English
Graduate Outcomes Presentation Slides - English
 

CakePHP workshop

  • 2. Walther Lalk CakePHP core team member Croogo core team member Lead Software Developer at Troop Scouter at 9th Pretoria (Irene) Air Scouts Husband
  • 3. Development environment VirtualBox withVagrant Recommended vagrant box is the FriendsOfCake vagrant box. Download it by running $ git clone https://github.com/FriendsOfCake/vagrant-chef.git Then start the vagrant box up with $ cd vagrant-chef $ vagrant up $ vagrant ssh (For windows you’ll probably need to use Putty) Add this to your hosts file 192.168.13.37 app.dev Linux or OSX : /etc/hosts Windows: C:WindowsSystem32driversetchosts PHP built in server Ensure you have PHP 5.5.9+ with the Intl and Mbstring and a database server running (with the corresponding PDO extension). Supported: MySQL, PostgreSQL, SQLite, SQL Server I will be using this with SQLite.
  • 4. Following along at home https://github.com/dakota/phpsa2016-complete
  • 5. Installing CakePHP Run $ composer create-project cakephp/app app Then $ cd app
  • 6. If you are using the vagrant box, then visit http://app.dev in your browser. Otherwise, wait for the next slide
  • 7. PHP Server Run $ bin/cake server Visit http://localhost:8765/
  • 9. Database configuration If you’re using the Vagrant box, and have a green tick for database, then you’re good to go. PHP Server users probably need to do some config. Recommend simply using SQLite (It’s the easiest to get going). Open config/app.php Find the Datasources, replace the default datasource with 'default' => [ 'className' => 'CakeDatabaseConnection', 'driver' => 'CakeDatabaseDriverSqlite', 'database' => ROOT . DS . 'database.sqlite', 'encoding' => 'utf8', 'cacheMetadata' => true, 'quoteIdentifiers' => false, ],
  • 10. Bake a database $ bin/cake bake migration CreateMembers first_name:string last_name:string email:string created modified $ bin/cake bake migration CreateEvents title:string description:text start:datetime end:datetime created modified $ bin/cake bake migration CreateEventsMembers event_id:integer:primary member_id:integer:primary
  • 11. Bake a database The migration bake task can sometimes get confused with composite primary keys, and tries to make each primary key an autoincrement field. We need to fix that! Open config/Migrations/…_CreateEventsMembers.php and remove the two ‘autoIncrement’ => true, lines. If you are using SQLite, you need to open all the files in the config/Migrations, and change all instances of ‘default’ => null to be ‘default’ => ‘’
  • 12. Seed that database $ bin/cake bake seed Members Open config/Seeds/MembersSeed.php, and update the $data variable $data = [ [ 'first_name' => 'Walther', 'last_name' => 'Lalk', 'email' => 'waltherlalk@cakephp.org', 'created' => date('Y-m-d H:i:s'), 'modified' => date('Y-m-d H:i:s'), ] ];
  • 13. Seed that database $ bin/cake bake seed Events Open config/Seeds/EventsSeed.php, and update the $data variable $data = [ [ 'title' => 'PHP South Africa 2016', 'description' => '', 'start' => '2016-09-28 08:00', 'end' => '2016-09-30 17:00', 'created' => date('Y-m-d H:i:s'), 'modified' => date('Y-m-d H:i:s'), ] ];
  • 14. Running migrations $ bin/cake migrations migrate $ bin/cake migrations seed
  • 15. Bake your application $ bin/cake bake all Members $ bin/cake bake all Events Visit /members in your browser, there should be 1 member. Add another one. Now visit /events in your browser, there should be 1 event. Add another one. Notice how both of them have a multi-select box for members or events? We’re going to remove that at a later stage and change how it works.
  • 16. Anatomy of a CakePHP application
  • 19. Validation Open src/Model/Table/EventsTable.php, find in the validationDefault method. Change notEmpty() to be allowEmpty() $validator ->requirePresence('description', 'create') ->notEmpty('description');
  • 20. Application rules public function buildRules(RulesChecker $rules) { $rules->add( function (Event $event) { return $event->start <= $event->end; }, 'endAfterStart', [ 'errorField' => 'end', 'message' => 'The event cannot end before it has started' ] ); return parent::buildRules($rules); }
  • 21. The art of knowing who’s there
  • 22. Adding a password $ bin/cake bake migration AddPasswordToMembers password:string[60] $ bin/cake migrations migrate Add to src/Model/Entity/MemberEntity.php protected function _setPassword($password) { if (strlen($password) > 0) { return (new CakeAuthDefaultPasswordHasher())->hash($password); } return $this->password; }
  • 23. Adding a password Add to src/Templates/Members/add.ctp and src/Templates/Members/edit.ctp echo $this->Form->input('password', [ 'value' => '' ]); echo $this->Form->input('password_confirm', [ 'label' => 'Confirm password', ’type' => 'password', 'value' => '' ]);
  • 24. Adding a password Add validation to the password, and password confirmation fields. $validator ->requirePresence('password', 'create') ->notEmpty('password', 'You need to provide a password.', 'create') ->minLength('password', 6, 'Your password must be 6 characters or longer'); $condition = function ($context) { return !empty($context['data']['password']); }; $validator ->requirePresence('password_confirm', $condition) ->notEmpty('password_confirm', 'Please confirm your password', $condition) ->add('password_confirm', 'mustMatch', [ 'rule' => function ($check, $context) { return $context['data']['password'] === $check; }, 'on' => $condition, 'message' => 'Password does not match' ]);
  • 25. Adding a password Edit your existing members and give them passwords. They will be automatically hashed.
  • 26. Creating the login action Open src/Controller/MembersController.php public function login() { if ($this->request->is('post')) { $member = $this->Auth->identify(); if ($member) { $this->Auth->setUser($member); return $this->redirect($this->Auth->redirectUrl()); } else { $this->Flash->error(__('Email address or password is incorrect'), [ 'key' => 'auth' ]); } } } public function logout() { return $this->redirect($this->Auth->logout()); }
  • 27. Creating the login template Create src/Templates/Members/login.ctp <div class="login form large-12 columns content"> <?php echo $this->Form->create(); echo $this->Form->input('email'); echo $this->Form->input('password'); echo $this->Form->button('Login'); echo $this->Form->end(); ?> </div>
  • 28. Enabling Authentication Open src/Controller/AppController.php, and add to the initialize method. $this->loadComponent('Auth', [ 'loginAction' => [ 'controller' => 'Members', 'action' => 'login', ], 'authenticate' => [ 'Form' => [ 'fields' => ['username' => 'email', 'password' => 'password'], 'userModel' => 'Members' ] ] ]); Try to visit /members now
  • 29. Event security We are adding a organiser to our events. Only the organiser is allowed to change the event. $ bin/cake bake migration AddOrganiserToEvents organiser_id:integer $ bin/cake migrations migrate $this->belongsTo('Organiser', [ 'foreignKey' => 'organiser_id', 'className' => 'Members' ]); Open src/Model/Table/EventsTable.php, and add to the initialize method. Open src/Model/Table/MembersTable.php, and add to the initialize method. $this->hasMany('OrganisingEvents', [ 'foreignKey' => 'organiser_id', 'className' => 'Events' ]);
  • 30. Event security Enforce foreign key constraints at an application level by adding the following to the buildRules method in the EventsTable class. $rules->existsIn('organiser_id', 'Organiser', 'That member does not exist in the database.');
  • 31. Who’s the organiser? The member creating the event should be able to choose who the event organiser is. In src/Templates/Events/add.ctp echo $this->Form->input('organiser_id', [ 'empty' => '-- Select organiser --', 'options' => $members, 'default' => $this->request->session()->read('Auth.User.id') ]); In src/Templates/Events/edit.ctp echo $this->Form->input('organiser_id', [ 'empty' => '-- Select organiser --', 'options' => $members, ]);
  • 32. Who’s that? Who is organiser 1? protected $_virtual = [ 'full_name' ]; protected function _getFullName() { return sprintf('%s %s (%s)', $this->first_name, $this->last_name, $this->email); } Add to the Member entity class In the MembersTable class, change the displayField to ‘full_name’ Better!
  • 33. Event security To enforce that an event can only be modified by it’s organiser, open src/Controller/EventsController.php and add to the edit method, just after the get() call. if ($event->organiser_id !== $this->Auth->user('id')) { throw new ForbiddenException(); }
  • 34. Member security To prevent a member from editing another member’s profile, simply add if ($id !== $this->Auth->user('id')) { throw new ForbiddenException(); } To the edit method in the MembersController.
  • 35. Allow registrations Allow new members to register by adding a beforeFilter method to the MembersController. public function beforeFilter(CakeEventEvent $event) { $this->Auth->allow('add'); return parent::beforeFilter($event); } Add make a pretty URL for registration and login. Add to config/routes.php $routes->connect('/register', ['controller' => 'Members', 'action' => 'add']); $routes->connect('/login', ['controller' => 'Members', 'action' => 'login']);
  • 37. Belongs to many Create a join table object $ bin/cake bake model EventsMembers Change 'joinTable' => 'events_members' to 'through' => 'EventsMembers', 'saveStrategy' => CakeORMAssociationBelongsToMany::SAVE_APPEND in the Members and Events table objects.
  • 38. Event attendance Add a field to capture the type of event attendance $ bin/cake bake migration AddTypeToEventsMembers type:string[10] $ bin/cake migrations migrate Add to EventsMember entity const TYPE_GOING = 'going'; const TYPE_INTERESTED = 'interested'; const TYPE_NOT_GOING = 'notGoing';
  • 39. Event attendance In EventsTable, add public function linkMember(AppModelEntityEvent $event, $memberId, $type) { $member = $this->Members->get($memberId); //Add the join data $member->_joinData = new AppModelEntityEventsMember([ 'type' => $type ]); return $this->association('Members')->link($event, [$member]); }
  • 40. Event attendance In EventsController, add public function linkActiveMember($eventId, $type) { $event = $this->Events->get($eventId); if ($this->Events->linkMember($event, $this->Auth->user('id'), $type)) { $this->Flash->success('Registered!'); } else { $this->Flash->error('Something went wrong.'); } return $this->redirect($this->referer()); }
  • 41. Event attendance In the Event entity public function memberStatus($memberId, $type) { if (!$this->has('members')) { return false; } $member = collection($this->members) ->firstMatch(['id' => $memberId]); if (!$member) { return false; } return $member->_joinData->type === $type; }
  • 42. Event attendance In src/Template/Events/index.ctp, in the actions table cell <br> <?php if (!$event->memberStatus($this->request->session() ->read('Auth.User.id'), AppModelEntityEventsMember::TYPE_GOING) ) { echo $this->Html->link(__('Going'), [ 'action' => 'linkActiveMember', $event->id, AppModelEntityEventsMember::TYPE_GOING ]); } if (!$event->memberStatus($this->request->session() ->read('Auth.User.id'), AppModelEntityEventsMember::TYPE_INTERESTED) ) { echo $this->Html->link(__('Interested'), [ 'action' => 'linkActiveMember', $event->id, AppModelEntityEventsMember::TYPE_INTERESTED ]); } if (!$event->memberStatus($this->request->session() ->read('Auth.User.id'), AppModelEntityEventsMember::TYPE_NOT_GOING) ) { echo $this->Html->link(__('Not going'), [ 'action' => 'linkActiveMember', $event->id, AppModelEntityEventsMember::TYPE_NOT_GOING ]); } ?>
  • 43. Event attendance Open src/Templates/Events/add.ctp and src/Templates/Events/edit.ctp and remove echo $this->Form->input('members._ids', ['options' => $members]); Open src/Templates/Members/add.ctp and src/Templates/Members/edit.ctp and remove echo $this->Form->input('events._ids', ['options' => $events]);
  • 44. We don’t need code where we’re going
  • 45. Installing CRUD $ composer require friendsofcake/crud $ bin/cake plugin load Crud use CrudControllerControllerTrait; Add the Crud trait to your AppController And, load the Crud component in the initialize method $this->loadComponent('Crud.Crud', [ 'actions' => [ 'Crud.Index', 'Crud.View', 'Crud.Edit', 'Crud.Add', 'Crud.Delete' ], 'listeners' => [ 'Crud.RelatedModels' ] ]);
  • 46. Remove all your code Or, at least all index, view, edit, add and delete actions.
  • 47. It still works!? Thanks to the power of CRUD, everything still works (Mostly)
  • 48. Adding back functionality Create a AuthListener class in the src/Listener directory <?php namespace AppListener; use CakeEventEvent; use CakeNetworkExceptionForbiddenException; use CrudListenerBaseListener; /** * Class AuthListener */ class AuthListener extends BaseListener { /** * Settings * * @var array */ protected $_defaultConfig = [ 'property' => 'id', 'message' => 'You are not allowed to access the requested resource.', 'actions' => ['edit', 'delete'] ];
  • 49. Adding back functionality public function afterFind(Event $event) { if (!in_array($this->_request()->param('action'), $this->config('actions')) ) { return; } $entity = $event->subject()->entity; $userId = $this->_controller()->Auth->user('id'); if ($entity->get($this->config('property')) !== $userId) { throw new ForbiddenException($this->config('message')); } } }
  • 50. Adding back functionality MembersController beforeFilter, add: $this->Crud->addListener('Auth', 'Auth', [ 'property' => 'id' ]); Add a beforeFilter for EventsController public function beforeFilter(CakeEventEvent $event) { $this->Crud->addListener('Auth', 'Auth', [ 'property' => 'organiser_id' ]); return parent::beforeFilter($event); }