SlideShare a Scribd company logo
1 of 28
Download to read offline
Advanced Querying with
CakePHP 3
1 / 28
Agenda
1. A short story
2. The philosophy behind the new ORM
3. The ORM goals
4. Simple Querying
5. Using SQL Functions
6. Subqueries
7. Working with associations
8. Associations Strategies
9. Filtering by Associations
10. Raw expressions and Deep Associations
11. Formatting your results
12. Intelligent Counters
2 / 28
A Short Story
Once upon a time there was a framework that worked like...
$this->Post->recursive = 3;
$this->Post->find('all');
And there was much rejoice, and then much sadness.
3 / 28
The Philosophy Behind the
New ORM
Understanding the ideas that brought us here will help you use effectively the ORM,
and enjoy using databases again.
4 / 28
The R in ORM
In 2010 I wrote a CakePHP datasource plugin for using MongoDB.
I thought it was cool.
b0ss: Can you please get last workshop attendees' emails?
me: Wait a minute, I need to write a custom Javascript program to get that data
It took much longer than a minute.
Relational databases won't go away anytime soon
They are extremely efficient
SQL is declarative language, even non programmers can get good at it
Allow you to query your data in any angle
5 / 28
No intentions of being
more than an ORM
This means:
Not going to connect to stuff that is not a relational database
We can focus on getting the most of of relational features
No incomplete abstractions
Does not mean:
That CakePHP 3 can't use NoSQL storage.
That you will spend hours scratching your head trying to wrap an API around a
fixed Interface.
6 / 28
Goals we had in mind
7 / 28
Clean layers
Each part of the subsystem should be usable on its own.
// OMG I'm not even using the ORM
$connection->newQuery()->select('*')->from('users');
// Ok, now I am
$table = TableRegistry::get('users');
$table->find();
8 / 28
Extensible column types
system
Do you really need ENUM? Go for it!
Type::map('enum', 'EnumType');
$users->schema()->columnType('role', 'enum');
9 / 28
Lazy (almost) all the things.
No database connections unless necessary.
No Queries executed unless needed.
// Look ma', no database connection have been made yet!
$users->find('all')->where(['username' => 'jose_zap']);
// Query was executed, nothing in memory yet
$users->find('all')->where(['username' => 'jose_zap'])->all();
// Only keep one row in memory at a time
$users->find('all')->where(['username' => 'jose_zap'])->bufferResults(false);
10 / 28
Should be fun to work with
Everything can be an expression
$query = $users->find()->select(['id'])->where(['is_active' => true]);
$anotherQuery->from(['stuff' => $query]);
$anotherQuery->innerJoin(['stuff' => $query]);
$anotherQuery->where(['id IN' => $query]);
Queries can be composed
$premium = $users->find('active')->find('premium')->each(function($user) {
echo $user->name;
});
$subscribers = $users->find('active')->find('subscribedToNewsletter');
$recipients = $premium->append($free)->extract('email');
11 / 28
The Setup
class CountriesTable extends Table {
public function initialize(array $config) {
$this->table('countries');
$this->belongsTo('Capitals', [
'foreignKey' => 'capital_id',
]);
$this->hasMany('Cities', [
'foreignKey' => 'country_id',
]);
$this->hasMany('Languages', [
'foreignKey' => 'country_id',
]);
}
12 / 28
Simple Querying
Monarchies with the largest population
public function findBiggestMonarchies(Query $query) {
return $query
->where(['government_form LIKE' => '%Monarchy%'])
->order(['population' => 'DESC']);
}
{
"name": "Japan",
"population": 126714000
},
{
"name": "Thailand",
"population": 61399000
},
{
"name": "United Kingdom",
"population": 59623400
},
13 / 28
Simple Querying
Republics in the world
public function findRepublics(Query $query) {
return $query
->where(['government_form' => 'Republic'])
->orWhere(['government_form' => 'Federal Republic']);
}
14 / 28
SQL Functions
Average life expectancy
public function findAverageLifeExpectancy(Query $query) {
return $query->select(['average_exp' => $query->func()->avg('life_expectancy')]);
}
{
"average_exp": 66.48604
}
15 / 28
Subqueries
public function findWithHighLifeExp(Query $query) {
$average = $this->find('findAverageLifeExpectancy');
return $query
->where(['life_expectancy >' => $average])
->order(['life_expectancy' => 'DESC']);
}
$countries->find('republics')->find('withHighLifeExp');
Republics with high life expectancy:
{
"name": "San Marino",
"life_expectancy": 81.1
},
{
"name": "Singapore",
"life_expectancy": 80.1
},
{
"name": "Iceland",
"life_expectancy": 79.4
}
16 / 28
Working with associations
$this->hasOne('OfficialLanguages', [
'className' => LanguagesTable::class,
'foreignKey' => 'country_id',
'conditions' => ['OfficialLanguages.is_official' => 'T']
]);
Official Languages
public function findWithOfficialLanguage(Query $query) {
return $query
->contain('OfficialLanguages');
}
17 / 28
Association strategies
public function findWithSpokenLanguages(Query $query, $options = []) {
if (!empty($options['languageStrategy'])) {
$this->Languages->strategy($options['languageStrategy']);
}
return $query
->contain('Languages');
}
Change the strategy:
$countries->find('withSpokenLanguages', ['languageStrategy' => 'subquery'])
And expect this SQL to be used:
SELECT * FROM languages AS Languages
WHERE country_id IN (SELECT id FROM countries AS Countries)
18 / 28
Filtering by associations
Cities with a population larger than
Denmark
public function findWithCitiesBiggerThanDenmark(Query $query) {
$denmarkPopulation = $this->find()
->select(['population'])
->where(['id' => 'DNK']);
return $query
->distinct(['Countries.id'])
->matching('Cities', function($q) use ($denmarkPopulation) {
return $q->where(['Cities.population >' => $denmarkPopulation]);
});
}
19 / 28
Raw SQL and Deep Assocs
I want to learn a new language, so I need to go to a city where that language is
spoken by at least 25% of the people who live there:
public function findCityProbability(Query $query) {
return $query
->matching('Countries.Cities', function($q) {
$prob = $q->newExpr(
'(Languages.percentage / 100) *' .
'(Cities.population / Countries.population)'
);
return $q
->select(['probability' => $prob, 'Cities.name'])
->where(function($exp) use ($prob) {
return $exp->gte($prob, 0.25);
});
});
}
20 / 28
Post processing
Things to keep in mind
Custom finders are required to return a Query object
Returning an array or a single value is not a Query
Therefore, you cannot return arrays or any other value
The Solution
Use formatResults()
Use mapReduce()
Use any of the Collection class methods after calling find()
21 / 28
Grouping by a Property
public function findInContinentGroups(Query $query) {
$query->formatResults(function($results) {
return $results->groupBy('continent');
});
return $query;
}
"Africa": [
{
"name": "Angola"
},
{
"name": "Burundi"
},
{
"name": "Benin"
},
{
"name": "Burkina Faso"
}
"America": [...
22 / 28
Getting Key - Value Lists
public function findOfficialLanguageList(Query $query) {
$query->formatResults(function($results) {
return $results->combine('name', 'official_language.language');
});
return $query->find('withOfficialLanguage');
}
{
"Aruba": "Dutch",
"Afghanistan": "Pashto",
"Albania": "Albaniana",
"Andorra": "Catalan",
"Netherlands Antilles": "Papiamento",
"United Arab Emirates": "Arabic",
"Argentina": "Spanish",
"Armenia": "Armenian",
...
23 / 28
Multiple Formatters
public function findInRegionalGroups(Query $query) {
$query
->formatResults(function($results) {
return $results->groupBy('continent');
})
->formatResults(function($results) {
return $results->map(function($continent) {
return collection($continent)->groupBy('region');
});
});
return $query;
}
"North America": {
"Caribbean": [
{
"name": "Aruba"
},
{
"name": "Anguilla"
},
{
"name": "Netherlands Antilles"
}
...
24 / 28
Intelligent Counts
$countries->find()
->select(function($query) {
return [
'average_life_expectancy' => $query->func()->avg('life_expectancy'),
'continent'
});
->group(['continent'])
->count(); // 7
Produces the following SQL:
SELECT COUNT(*) AS `count`
FROM (
SELECT (AVG(life_expectancy)), Countries.continent
FROM countries AS Countries GROUP BY continent
)
AS count_source
Pagination: piece of cake!
25 / 28
I have 99 problems...
Custom counting ain't one
Don't care about actual results counting in a pagination query?
Prefer using estimates or a different logic?
Use custom counters!
$query = $youtubeVideos->find('superComplexStuff')->counter(function() {
return Cache::read('estimated_results');
});
$query->count(); // 10000000
26 / 28
There's Plenty More!
But unfortunately, little time...
Result streaming
Query caching
Finder callbacks
Composite Primary Key searches
Methods for finding in Tree structures
27 / 28
Thanks for your time
Questions?
https://github.com/lorenzo/cakephp3-examples
28 / 28

More Related Content

What's hot

Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Adob...
Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Adob...Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Adob...
Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Adob...Uma Ghotikar
 
Asterisk, HTML5 and NodeJS; a world of endless possibilities
Asterisk, HTML5 and NodeJS; a world of endless possibilitiesAsterisk, HTML5 and NodeJS; a world of endless possibilities
Asterisk, HTML5 and NodeJS; a world of endless possibilitiesDan Jenkins
 
Introduction to jQuery
Introduction to jQueryIntroduction to jQuery
Introduction to jQuerymanugoel2003
 
Full Stack Web Development.pptx
Full Stack Web Development.pptxFull Stack Web Development.pptx
Full Stack Web Development.pptxDineshGokuladas
 
Java 8 Stream API. A different way to process collections.
Java 8 Stream API. A different way to process collections.Java 8 Stream API. A different way to process collections.
Java 8 Stream API. A different way to process collections.David Gómez García
 
Entity provider selection confusion attacks in JAX-RS applications
Entity provider selection confusion attacks in JAX-RS applicationsEntity provider selection confusion attacks in JAX-RS applications
Entity provider selection confusion attacks in JAX-RS applicationsMikhail Egorov
 
Google I/O 2018 Extended, Baghdad - Flutter
Google I/O 2018 Extended, Baghdad  - FlutterGoogle I/O 2018 Extended, Baghdad  - Flutter
Google I/O 2018 Extended, Baghdad - FlutterAbdElmomenKadhim
 

What's hot (12)

Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Adob...
Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Adob...Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Adob...
Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Adob...
 
Clean Code
Clean CodeClean Code
Clean Code
 
PHP POWERPOINT SLIDES
PHP POWERPOINT SLIDESPHP POWERPOINT SLIDES
PHP POWERPOINT SLIDES
 
Asterisk, HTML5 and NodeJS; a world of endless possibilities
Asterisk, HTML5 and NodeJS; a world of endless possibilitiesAsterisk, HTML5 and NodeJS; a world of endless possibilities
Asterisk, HTML5 and NodeJS; a world of endless possibilities
 
Introduction to jQuery
Introduction to jQueryIntroduction to jQuery
Introduction to jQuery
 
Full Stack Web Development.pptx
Full Stack Web Development.pptxFull Stack Web Development.pptx
Full Stack Web Development.pptx
 
Java 8 Stream API. A different way to process collections.
Java 8 Stream API. A different way to process collections.Java 8 Stream API. A different way to process collections.
Java 8 Stream API. A different way to process collections.
 
Entity provider selection confusion attacks in JAX-RS applications
Entity provider selection confusion attacks in JAX-RS applicationsEntity provider selection confusion attacks in JAX-RS applications
Entity provider selection confusion attacks in JAX-RS applications
 
JDBC – Java Database Connectivity
JDBC – Java Database ConnectivityJDBC – Java Database Connectivity
JDBC – Java Database Connectivity
 
C Programming Exam problems & Solution by sazzad hossain
C Programming Exam problems & Solution by sazzad hossainC Programming Exam problems & Solution by sazzad hossain
C Programming Exam problems & Solution by sazzad hossain
 
Google I/O 2018 Extended, Baghdad - Flutter
Google I/O 2018 Extended, Baghdad  - FlutterGoogle I/O 2018 Extended, Baghdad  - Flutter
Google I/O 2018 Extended, Baghdad - Flutter
 
Introduction to Qt
Introduction to QtIntroduction to Qt
Introduction to Qt
 

Similar to Advanced Querying with CakePHP 3

Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Jeff Carouth
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolveXSolve
 
PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applicationselliando dias
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
Modularity and Layered Data Model
Modularity and Layered Data ModelModularity and Layered Data Model
Modularity and Layered Data ModelAttila Jenei
 
Auto-loading of Drupal CCK Nodes
Auto-loading of Drupal CCK NodesAuto-loading of Drupal CCK Nodes
Auto-loading of Drupal CCK Nodesnihiliad
 
ZendCon2010 The Doctrine Project
ZendCon2010 The Doctrine ProjectZendCon2010 The Doctrine Project
ZendCon2010 The Doctrine ProjectJonathan Wage
 
Easy rest service using PHP reflection api
Easy rest service using PHP reflection apiEasy rest service using PHP reflection api
Easy rest service using PHP reflection apiMatthieu Aubry
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applicationschartjes
 
How to write not breakable unit tests
How to write not breakable unit testsHow to write not breakable unit tests
How to write not breakable unit testsRafal Ksiazek
 
Digital Mayflower - Data Pilgrimage with the Drupal Migrate Module
Digital Mayflower - Data Pilgrimage with the Drupal Migrate ModuleDigital Mayflower - Data Pilgrimage with the Drupal Migrate Module
Digital Mayflower - Data Pilgrimage with the Drupal Migrate ModuleErich Beyrent
 
PHP 5.3 Overview
PHP 5.3 OverviewPHP 5.3 Overview
PHP 5.3 Overviewjsmith92
 
Durian: a PHP 5.5 microframework with generator-style middleware
Durian: a PHP 5.5 microframework with generator-style middlewareDurian: a PHP 5.5 microframework with generator-style middleware
Durian: a PHP 5.5 microframework with generator-style middlewareKuan Yen Heng
 
PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applicationselliando dias
 
Practical PHP 5.3
Practical PHP 5.3Practical PHP 5.3
Practical PHP 5.3Nate Abele
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodeSWIFTotter Solutions
 

Similar to Advanced Querying with CakePHP 3 (20)

Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolve
 
2013 - Benjamin Eberlei - Doctrine 2
2013 - Benjamin Eberlei - Doctrine 22013 - Benjamin Eberlei - Doctrine 2
2013 - Benjamin Eberlei - Doctrine 2
 
PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applications
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Modularity and Layered Data Model
Modularity and Layered Data ModelModularity and Layered Data Model
Modularity and Layered Data Model
 
Auto-loading of Drupal CCK Nodes
Auto-loading of Drupal CCK NodesAuto-loading of Drupal CCK Nodes
Auto-loading of Drupal CCK Nodes
 
ZendCon2010 The Doctrine Project
ZendCon2010 The Doctrine ProjectZendCon2010 The Doctrine Project
ZendCon2010 The Doctrine Project
 
Easy rest service using PHP reflection api
Easy rest service using PHP reflection apiEasy rest service using PHP reflection api
Easy rest service using PHP reflection api
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applications
 
Agile database access with CakePHP 3
Agile database access with CakePHP 3Agile database access with CakePHP 3
Agile database access with CakePHP 3
 
How to write not breakable unit tests
How to write not breakable unit testsHow to write not breakable unit tests
How to write not breakable unit tests
 
Digital Mayflower - Data Pilgrimage with the Drupal Migrate Module
Digital Mayflower - Data Pilgrimage with the Drupal Migrate ModuleDigital Mayflower - Data Pilgrimage with the Drupal Migrate Module
Digital Mayflower - Data Pilgrimage with the Drupal Migrate Module
 
Backbone js
Backbone jsBackbone js
Backbone js
 
PHP 5.3 Overview
PHP 5.3 OverviewPHP 5.3 Overview
PHP 5.3 Overview
 
Durian: a PHP 5.5 microframework with generator-style middleware
Durian: a PHP 5.5 microframework with generator-style middlewareDurian: a PHP 5.5 microframework with generator-style middleware
Durian: a PHP 5.5 microframework with generator-style middleware
 
PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applications
 
Practical PHP 5.3
Practical PHP 5.3Practical PHP 5.3
Practical PHP 5.3
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better Code
 
RESTful web services
RESTful web servicesRESTful web services
RESTful web services
 

More from José Lorenzo Rodríguez Urdaneta (6)

Faster develoment with CakePHP 3
Faster develoment with CakePHP 3Faster develoment with CakePHP 3
Faster develoment with CakePHP 3
 
CakeFest 2013 keynote
CakeFest 2013 keynoteCakeFest 2013 keynote
CakeFest 2013 keynote
 
CakePHP 3.0: Embracing the future
CakePHP 3.0: Embracing the futureCakePHP 3.0: Embracing the future
CakePHP 3.0: Embracing the future
 
ZeroMQ in PHP
ZeroMQ in PHPZeroMQ in PHP
ZeroMQ in PHP
 
Making the most out of CakePHP 2.2
Making the most out of CakePHP 2.2Making the most out of CakePHP 2.2
Making the most out of CakePHP 2.2
 
Mongo Cake Plugin for CakePHP 2.0
Mongo Cake Plugin for CakePHP 2.0Mongo Cake Plugin for CakePHP 2.0
Mongo Cake Plugin for CakePHP 2.0
 

Recently uploaded

Speed Wins: From Kafka to APIs in Minutes
Speed Wins: From Kafka to APIs in MinutesSpeed Wins: From Kafka to APIs in Minutes
Speed Wins: From Kafka to APIs in Minutesconfluent
 
AI presentation and introduction - Retrieval Augmented Generation RAG 101
AI presentation and introduction - Retrieval Augmented Generation RAG 101AI presentation and introduction - Retrieval Augmented Generation RAG 101
AI presentation and introduction - Retrieval Augmented Generation RAG 101vincent683379
 
How we scaled to 80K users by doing nothing!.pdf
How we scaled to 80K users by doing nothing!.pdfHow we scaled to 80K users by doing nothing!.pdf
How we scaled to 80K users by doing nothing!.pdfSrushith Repakula
 
Google I/O Extended 2024 Warsaw
Google I/O Extended 2024 WarsawGoogle I/O Extended 2024 Warsaw
Google I/O Extended 2024 WarsawGDSC PJATK
 
Structuring Teams and Portfolios for Success
Structuring Teams and Portfolios for SuccessStructuring Teams and Portfolios for Success
Structuring Teams and Portfolios for SuccessUXDXConf
 
ECS 2024 Teams Premium - Pretty Secure
ECS 2024   Teams Premium - Pretty SecureECS 2024   Teams Premium - Pretty Secure
ECS 2024 Teams Premium - Pretty SecureFemke de Vroome
 
Intro in Product Management - Коротко про професію продакт менеджера
Intro in Product Management - Коротко про професію продакт менеджераIntro in Product Management - Коротко про професію продакт менеджера
Intro in Product Management - Коротко про професію продакт менеджераMark Opanasiuk
 
Behind the Scenes From the Manager's Chair: Decoding the Secrets of Successfu...
Behind the Scenes From the Manager's Chair: Decoding the Secrets of Successfu...Behind the Scenes From the Manager's Chair: Decoding the Secrets of Successfu...
Behind the Scenes From the Manager's Chair: Decoding the Secrets of Successfu...CzechDreamin
 
Powerful Start- the Key to Project Success, Barbara Laskowska
Powerful Start- the Key to Project Success, Barbara LaskowskaPowerful Start- the Key to Project Success, Barbara Laskowska
Powerful Start- the Key to Project Success, Barbara LaskowskaCzechDreamin
 
Optimizing NoSQL Performance Through Observability
Optimizing NoSQL Performance Through ObservabilityOptimizing NoSQL Performance Through Observability
Optimizing NoSQL Performance Through ObservabilityScyllaDB
 
What's New in Teams Calling, Meetings and Devices April 2024
What's New in Teams Calling, Meetings and Devices April 2024What's New in Teams Calling, Meetings and Devices April 2024
What's New in Teams Calling, Meetings and Devices April 2024Stephanie Beckett
 
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo DiehlFuture Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo DiehlPeter Udo Diehl
 
Portal Kombat : extension du réseau de propagande russe
Portal Kombat : extension du réseau de propagande russePortal Kombat : extension du réseau de propagande russe
Portal Kombat : extension du réseau de propagande russe中 央社
 
Syngulon - Selection technology May 2024.pdf
Syngulon - Selection technology May 2024.pdfSyngulon - Selection technology May 2024.pdf
Syngulon - Selection technology May 2024.pdfSyngulon
 
The Metaverse: Are We There Yet?
The  Metaverse:    Are   We  There  Yet?The  Metaverse:    Are   We  There  Yet?
The Metaverse: Are We There Yet?Mark Billinghurst
 
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdfThe Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdfFIDO Alliance
 
Breaking Down the Flutterwave Scandal What You Need to Know.pdf
Breaking Down the Flutterwave Scandal What You Need to Know.pdfBreaking Down the Flutterwave Scandal What You Need to Know.pdf
Breaking Down the Flutterwave Scandal What You Need to Know.pdfUK Journal
 
AI revolution and Salesforce, Jiří Karpíšek
AI revolution and Salesforce, Jiří KarpíšekAI revolution and Salesforce, Jiří Karpíšek
AI revolution and Salesforce, Jiří KarpíšekCzechDreamin
 
TopCryptoSupers 12thReport OrionX May2024
TopCryptoSupers 12thReport OrionX May2024TopCryptoSupers 12thReport OrionX May2024
TopCryptoSupers 12thReport OrionX May2024Stephen Perrenod
 
Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...
Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...
Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...FIDO Alliance
 

Recently uploaded (20)

Speed Wins: From Kafka to APIs in Minutes
Speed Wins: From Kafka to APIs in MinutesSpeed Wins: From Kafka to APIs in Minutes
Speed Wins: From Kafka to APIs in Minutes
 
AI presentation and introduction - Retrieval Augmented Generation RAG 101
AI presentation and introduction - Retrieval Augmented Generation RAG 101AI presentation and introduction - Retrieval Augmented Generation RAG 101
AI presentation and introduction - Retrieval Augmented Generation RAG 101
 
How we scaled to 80K users by doing nothing!.pdf
How we scaled to 80K users by doing nothing!.pdfHow we scaled to 80K users by doing nothing!.pdf
How we scaled to 80K users by doing nothing!.pdf
 
Google I/O Extended 2024 Warsaw
Google I/O Extended 2024 WarsawGoogle I/O Extended 2024 Warsaw
Google I/O Extended 2024 Warsaw
 
Structuring Teams and Portfolios for Success
Structuring Teams and Portfolios for SuccessStructuring Teams and Portfolios for Success
Structuring Teams and Portfolios for Success
 
ECS 2024 Teams Premium - Pretty Secure
ECS 2024   Teams Premium - Pretty SecureECS 2024   Teams Premium - Pretty Secure
ECS 2024 Teams Premium - Pretty Secure
 
Intro in Product Management - Коротко про професію продакт менеджера
Intro in Product Management - Коротко про професію продакт менеджераIntro in Product Management - Коротко про професію продакт менеджера
Intro in Product Management - Коротко про професію продакт менеджера
 
Behind the Scenes From the Manager's Chair: Decoding the Secrets of Successfu...
Behind the Scenes From the Manager's Chair: Decoding the Secrets of Successfu...Behind the Scenes From the Manager's Chair: Decoding the Secrets of Successfu...
Behind the Scenes From the Manager's Chair: Decoding the Secrets of Successfu...
 
Powerful Start- the Key to Project Success, Barbara Laskowska
Powerful Start- the Key to Project Success, Barbara LaskowskaPowerful Start- the Key to Project Success, Barbara Laskowska
Powerful Start- the Key to Project Success, Barbara Laskowska
 
Optimizing NoSQL Performance Through Observability
Optimizing NoSQL Performance Through ObservabilityOptimizing NoSQL Performance Through Observability
Optimizing NoSQL Performance Through Observability
 
What's New in Teams Calling, Meetings and Devices April 2024
What's New in Teams Calling, Meetings and Devices April 2024What's New in Teams Calling, Meetings and Devices April 2024
What's New in Teams Calling, Meetings and Devices April 2024
 
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo DiehlFuture Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
 
Portal Kombat : extension du réseau de propagande russe
Portal Kombat : extension du réseau de propagande russePortal Kombat : extension du réseau de propagande russe
Portal Kombat : extension du réseau de propagande russe
 
Syngulon - Selection technology May 2024.pdf
Syngulon - Selection technology May 2024.pdfSyngulon - Selection technology May 2024.pdf
Syngulon - Selection technology May 2024.pdf
 
The Metaverse: Are We There Yet?
The  Metaverse:    Are   We  There  Yet?The  Metaverse:    Are   We  There  Yet?
The Metaverse: Are We There Yet?
 
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdfThe Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
 
Breaking Down the Flutterwave Scandal What You Need to Know.pdf
Breaking Down the Flutterwave Scandal What You Need to Know.pdfBreaking Down the Flutterwave Scandal What You Need to Know.pdf
Breaking Down the Flutterwave Scandal What You Need to Know.pdf
 
AI revolution and Salesforce, Jiří Karpíšek
AI revolution and Salesforce, Jiří KarpíšekAI revolution and Salesforce, Jiří Karpíšek
AI revolution and Salesforce, Jiří Karpíšek
 
TopCryptoSupers 12thReport OrionX May2024
TopCryptoSupers 12thReport OrionX May2024TopCryptoSupers 12thReport OrionX May2024
TopCryptoSupers 12thReport OrionX May2024
 
Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...
Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...
Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...
 

Advanced Querying with CakePHP 3

  • 2. Agenda 1. A short story 2. The philosophy behind the new ORM 3. The ORM goals 4. Simple Querying 5. Using SQL Functions 6. Subqueries 7. Working with associations 8. Associations Strategies 9. Filtering by Associations 10. Raw expressions and Deep Associations 11. Formatting your results 12. Intelligent Counters 2 / 28
  • 3. A Short Story Once upon a time there was a framework that worked like... $this->Post->recursive = 3; $this->Post->find('all'); And there was much rejoice, and then much sadness. 3 / 28
  • 4. The Philosophy Behind the New ORM Understanding the ideas that brought us here will help you use effectively the ORM, and enjoy using databases again. 4 / 28
  • 5. The R in ORM In 2010 I wrote a CakePHP datasource plugin for using MongoDB. I thought it was cool. b0ss: Can you please get last workshop attendees' emails? me: Wait a minute, I need to write a custom Javascript program to get that data It took much longer than a minute. Relational databases won't go away anytime soon They are extremely efficient SQL is declarative language, even non programmers can get good at it Allow you to query your data in any angle 5 / 28
  • 6. No intentions of being more than an ORM This means: Not going to connect to stuff that is not a relational database We can focus on getting the most of of relational features No incomplete abstractions Does not mean: That CakePHP 3 can't use NoSQL storage. That you will spend hours scratching your head trying to wrap an API around a fixed Interface. 6 / 28
  • 7. Goals we had in mind 7 / 28
  • 8. Clean layers Each part of the subsystem should be usable on its own. // OMG I'm not even using the ORM $connection->newQuery()->select('*')->from('users'); // Ok, now I am $table = TableRegistry::get('users'); $table->find(); 8 / 28
  • 9. Extensible column types system Do you really need ENUM? Go for it! Type::map('enum', 'EnumType'); $users->schema()->columnType('role', 'enum'); 9 / 28
  • 10. Lazy (almost) all the things. No database connections unless necessary. No Queries executed unless needed. // Look ma', no database connection have been made yet! $users->find('all')->where(['username' => 'jose_zap']); // Query was executed, nothing in memory yet $users->find('all')->where(['username' => 'jose_zap'])->all(); // Only keep one row in memory at a time $users->find('all')->where(['username' => 'jose_zap'])->bufferResults(false); 10 / 28
  • 11. Should be fun to work with Everything can be an expression $query = $users->find()->select(['id'])->where(['is_active' => true]); $anotherQuery->from(['stuff' => $query]); $anotherQuery->innerJoin(['stuff' => $query]); $anotherQuery->where(['id IN' => $query]); Queries can be composed $premium = $users->find('active')->find('premium')->each(function($user) { echo $user->name; }); $subscribers = $users->find('active')->find('subscribedToNewsletter'); $recipients = $premium->append($free)->extract('email'); 11 / 28
  • 12. The Setup class CountriesTable extends Table { public function initialize(array $config) { $this->table('countries'); $this->belongsTo('Capitals', [ 'foreignKey' => 'capital_id', ]); $this->hasMany('Cities', [ 'foreignKey' => 'country_id', ]); $this->hasMany('Languages', [ 'foreignKey' => 'country_id', ]); } 12 / 28
  • 13. Simple Querying Monarchies with the largest population public function findBiggestMonarchies(Query $query) { return $query ->where(['government_form LIKE' => '%Monarchy%']) ->order(['population' => 'DESC']); } { "name": "Japan", "population": 126714000 }, { "name": "Thailand", "population": 61399000 }, { "name": "United Kingdom", "population": 59623400 }, 13 / 28
  • 14. Simple Querying Republics in the world public function findRepublics(Query $query) { return $query ->where(['government_form' => 'Republic']) ->orWhere(['government_form' => 'Federal Republic']); } 14 / 28
  • 15. SQL Functions Average life expectancy public function findAverageLifeExpectancy(Query $query) { return $query->select(['average_exp' => $query->func()->avg('life_expectancy')]); } { "average_exp": 66.48604 } 15 / 28
  • 16. Subqueries public function findWithHighLifeExp(Query $query) { $average = $this->find('findAverageLifeExpectancy'); return $query ->where(['life_expectancy >' => $average]) ->order(['life_expectancy' => 'DESC']); } $countries->find('republics')->find('withHighLifeExp'); Republics with high life expectancy: { "name": "San Marino", "life_expectancy": 81.1 }, { "name": "Singapore", "life_expectancy": 80.1 }, { "name": "Iceland", "life_expectancy": 79.4 } 16 / 28
  • 17. Working with associations $this->hasOne('OfficialLanguages', [ 'className' => LanguagesTable::class, 'foreignKey' => 'country_id', 'conditions' => ['OfficialLanguages.is_official' => 'T'] ]); Official Languages public function findWithOfficialLanguage(Query $query) { return $query ->contain('OfficialLanguages'); } 17 / 28
  • 18. Association strategies public function findWithSpokenLanguages(Query $query, $options = []) { if (!empty($options['languageStrategy'])) { $this->Languages->strategy($options['languageStrategy']); } return $query ->contain('Languages'); } Change the strategy: $countries->find('withSpokenLanguages', ['languageStrategy' => 'subquery']) And expect this SQL to be used: SELECT * FROM languages AS Languages WHERE country_id IN (SELECT id FROM countries AS Countries) 18 / 28
  • 19. Filtering by associations Cities with a population larger than Denmark public function findWithCitiesBiggerThanDenmark(Query $query) { $denmarkPopulation = $this->find() ->select(['population']) ->where(['id' => 'DNK']); return $query ->distinct(['Countries.id']) ->matching('Cities', function($q) use ($denmarkPopulation) { return $q->where(['Cities.population >' => $denmarkPopulation]); }); } 19 / 28
  • 20. Raw SQL and Deep Assocs I want to learn a new language, so I need to go to a city where that language is spoken by at least 25% of the people who live there: public function findCityProbability(Query $query) { return $query ->matching('Countries.Cities', function($q) { $prob = $q->newExpr( '(Languages.percentage / 100) *' . '(Cities.population / Countries.population)' ); return $q ->select(['probability' => $prob, 'Cities.name']) ->where(function($exp) use ($prob) { return $exp->gte($prob, 0.25); }); }); } 20 / 28
  • 21. Post processing Things to keep in mind Custom finders are required to return a Query object Returning an array or a single value is not a Query Therefore, you cannot return arrays or any other value The Solution Use formatResults() Use mapReduce() Use any of the Collection class methods after calling find() 21 / 28
  • 22. Grouping by a Property public function findInContinentGroups(Query $query) { $query->formatResults(function($results) { return $results->groupBy('continent'); }); return $query; } "Africa": [ { "name": "Angola" }, { "name": "Burundi" }, { "name": "Benin" }, { "name": "Burkina Faso" } "America": [... 22 / 28
  • 23. Getting Key - Value Lists public function findOfficialLanguageList(Query $query) { $query->formatResults(function($results) { return $results->combine('name', 'official_language.language'); }); return $query->find('withOfficialLanguage'); } { "Aruba": "Dutch", "Afghanistan": "Pashto", "Albania": "Albaniana", "Andorra": "Catalan", "Netherlands Antilles": "Papiamento", "United Arab Emirates": "Arabic", "Argentina": "Spanish", "Armenia": "Armenian", ... 23 / 28
  • 24. Multiple Formatters public function findInRegionalGroups(Query $query) { $query ->formatResults(function($results) { return $results->groupBy('continent'); }) ->formatResults(function($results) { return $results->map(function($continent) { return collection($continent)->groupBy('region'); }); }); return $query; } "North America": { "Caribbean": [ { "name": "Aruba" }, { "name": "Anguilla" }, { "name": "Netherlands Antilles" } ... 24 / 28
  • 25. Intelligent Counts $countries->find() ->select(function($query) { return [ 'average_life_expectancy' => $query->func()->avg('life_expectancy'), 'continent' }); ->group(['continent']) ->count(); // 7 Produces the following SQL: SELECT COUNT(*) AS `count` FROM ( SELECT (AVG(life_expectancy)), Countries.continent FROM countries AS Countries GROUP BY continent ) AS count_source Pagination: piece of cake! 25 / 28
  • 26. I have 99 problems... Custom counting ain't one Don't care about actual results counting in a pagination query? Prefer using estimates or a different logic? Use custom counters! $query = $youtubeVideos->find('superComplexStuff')->counter(function() { return Cache::read('estimated_results'); }); $query->count(); // 10000000 26 / 28
  • 27. There's Plenty More! But unfortunately, little time... Result streaming Query caching Finder callbacks Composite Primary Key searches Methods for finding in Tree structures 27 / 28
  • 28. Thanks for your time Questions? https://github.com/lorenzo/cakephp3-examples 28 / 28