SlideShare uma empresa Scribd logo
1 de 28
Baixar para ler 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

Mais conteúdo relacionado

Mais procurados

Collections - Maps
Collections - Maps Collections - Maps
Collections - Maps Hitesh-Java
 
Dependency injection in CakePHP
Dependency injection in CakePHPDependency injection in CakePHP
Dependency injection in CakePHPmarkstory
 
Spring Framework
Spring Framework  Spring Framework
Spring Framework tola99
 
Shell Scripting Tutorial | Edureka
Shell Scripting Tutorial | EdurekaShell Scripting Tutorial | Edureka
Shell Scripting Tutorial | EdurekaEdureka!
 
JDBC - JPA - Spring Data
JDBC - JPA - Spring DataJDBC - JPA - Spring Data
JDBC - JPA - Spring DataArturs Drozdovs
 
Java database connectivity with MYSQL
Java database connectivity with MYSQLJava database connectivity with MYSQL
Java database connectivity with MYSQLAdil Mehmoood
 
Node.js Express
Node.js  ExpressNode.js  Express
Node.js ExpressEyal Vardi
 
7 rules of simple and maintainable code
7 rules of simple and maintainable code7 rules of simple and maintainable code
7 rules of simple and maintainable codeGeshan Manandhar
 
django Forms in a Web API World
django Forms in a Web API Worlddjango Forms in a Web API World
django Forms in a Web API WorldTareque Hossain
 
PUC SE Day 2019 - SpringBoot
PUC SE Day 2019 - SpringBootPUC SE Day 2019 - SpringBoot
PUC SE Day 2019 - SpringBootJosué Neis
 
Socket Programming In Python
Socket Programming In PythonSocket Programming In Python
Socket Programming In Pythondidip
 
Spring boot Introduction
Spring boot IntroductionSpring boot Introduction
Spring boot IntroductionJeevesh Pandey
 

Mais procurados (20)

Collections - Maps
Collections - Maps Collections - Maps
Collections - Maps
 
C Programming Unit-5
C Programming Unit-5C Programming Unit-5
C Programming Unit-5
 
laravel.pptx
laravel.pptxlaravel.pptx
laravel.pptx
 
Dependency injection in CakePHP
Dependency injection in CakePHPDependency injection in CakePHP
Dependency injection in CakePHP
 
Java 8 Lambda Expressions
Java 8 Lambda ExpressionsJava 8 Lambda Expressions
Java 8 Lambda Expressions
 
Xampp Ppt
Xampp PptXampp Ppt
Xampp Ppt
 
Java I/O
Java I/OJava I/O
Java I/O
 
Spring Framework
Spring Framework  Spring Framework
Spring Framework
 
Shell Scripting Tutorial | Edureka
Shell Scripting Tutorial | EdurekaShell Scripting Tutorial | Edureka
Shell Scripting Tutorial | Edureka
 
JDBC - JPA - Spring Data
JDBC - JPA - Spring DataJDBC - JPA - Spring Data
JDBC - JPA - Spring Data
 
Java database connectivity with MYSQL
Java database connectivity with MYSQLJava database connectivity with MYSQL
Java database connectivity with MYSQL
 
Node.js Express
Node.js  ExpressNode.js  Express
Node.js Express
 
7 rules of simple and maintainable code
7 rules of simple and maintainable code7 rules of simple and maintainable code
7 rules of simple and maintainable code
 
Php Tutorials for Beginners
Php Tutorials for BeginnersPhp Tutorials for Beginners
Php Tutorials for Beginners
 
django Forms in a Web API World
django Forms in a Web API Worlddjango Forms in a Web API World
django Forms in a Web API World
 
expression lambda
expression lambdaexpression lambda
expression lambda
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
PUC SE Day 2019 - SpringBoot
PUC SE Day 2019 - SpringBootPUC SE Day 2019 - SpringBoot
PUC SE Day 2019 - SpringBoot
 
Socket Programming In Python
Socket Programming In PythonSocket Programming In Python
Socket Programming In Python
 
Spring boot Introduction
Spring boot IntroductionSpring boot Introduction
Spring boot Introduction
 

Semelhante a 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
 

Semelhante a 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
 

Mais de 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
 

Último

A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfhans926745
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUK Journal
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEarley Information Science
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 

Último (20)

A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 

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