select
Select data from the table.
table [string]
The table name.
columns [array/string]
The target columns of data will be fetched.
table [string]
The table name.
columns [array/string]
The target columns of data will be fetched.
where (optional) [array]
The WHERE clause to filter records.
table [string]
The table name.
join [array]
Table relativity for tables. Ignore it if no table joining is required.
columns [array/string]
The target columns of data will be fetched.
where (optional) [array]
The WHERE clause to filter records.
*
as a columns parameter to fetch all columns, but we recommended providing all targeted columns for better performance and readability.$data = $database->select("account", [ "user_name", "email" ], [ "user_id[>]" => 100 ]); // $data = array( // [0] => array( // "user_name" => "foo", // "email" => "foo@bar.com" // ), // [1] => array( // "user_name" => "cat", // "email" => "cat@dog.com" // ) // ) foreach($data as $item) { echo "user_name:" . $item["user_name"] . " - email:" . $item["email"] . "<br/>"; } // Select all columns. $data = $database->select("account", "*"); // Select a column. $data = $database->select("account", "user_name"); // $data = array( // [0] => "foo", // [1] => "cat" // )
Traverse fetch with callback
While fetching data from a database, data will be first loaded into memory as an array variable and output back to the frontend.
If fetching a large amount of data from a database, the memory will be exhausted.
When passing the callback closure function ($data) {}
as the last parameter for select()
, it will output each data immediately without loading it into memory. That will be having a better performance for loading large amounts of data.
$database->select("account", ["name"], function ($data) { echo $data["name"]; }); $database->select("account", [ "name" ], function ($data) { echo $data["name"]; });
Performance Benchmark
Fetching 1,000, 5,000 and 20,000 different name data from MySQL database, and output it. Get memory usage via memory_get_usage()
.
// Method 1 $database->select("account", ["name"], function ($data) { echo $data["name"]; }); // vs // Method 2 $data = $database->select("account", ["name"]); foreach ($data as $item) { echo $item["name"]; }
Method 1 | Method 2 | |
1,000 Records | 789 KB | 1.2 MB |
5,000 Records | 1.1 MB | 3.3 MB |
20,000 Records | 2.26 MB | 11.1 MB |
Table joining
SQL JOIN clause can combine rows between two tables. Medoo provides a simple syntax for the JOIN clause.
- [>] ==> LEFT JOIN
- [<] ==> RIGHT JOIN
- [<>] ==> FULL JOIN
- [><] ==> INNER JOIN
$database->select("post", [ // Here is the table relativity argument that tells the relativity between the table you want to join. "[>]account" => ["author_id" => "user_id"] ], [ "post.title", "account.city" ]);
The row author_id
from the table post is equal to the row user_id
from the table account.
"[>]account" => ["author_id" => "user_id"]
LEFT JOIN "account" ON "post"."author_id" = "account"."user_id"
The row user_id
from the table post is equal to the row user_id
from the table album.
This is a shortcut to declare relativity if the row names are the same in both tables.
"[>]album" => "user_id"
LEFT JOIN "album" USING ("user_id")
post.user_id
is equal photo.user_id
and post.avatar_id
is equal photo.avatar_id
Like above, there are two rows or more that are the same in both tables.
"[>]photo" => ["user_id", "avatar_id"]
LEFT JOIN "photo" USING ("user_id", "avatar_id")
If you want to join the same table with different values, you have to assign the table with an alias.
"[>]account (replier)" => ["replier_id" => "user_id"]
LEFT JOIN "account" AS "replier" ON "post"."replier_id" = "replier"."user_id"
You can refer to the previously joined table by adding the table name before the column.
"[>]account" => ["author_id" => "user_id"], "[>]album" => ["account.user_id" => "user_id"]
LEFT JOIN "account" ON "post"."author_id" = "account"."user_id" LEFT JOIN "album" ON "account"."user_id" = "album"."user_id"
Multiple Conditions
"[>]account" => [ "author_id" => "user_id", "album.user_id" => "user_id" ]
LEFT JOIN "account" ON "account"."author_id" = "account"."user_id" AND "album"."user_id" = "account"."user_id"
Additional Condition
"[>]comment" => [ "author_id" => "user_id", "AND" => [ "rate[>]" => 50 ] ]
LEFT JOIN "comment" ON "account"."author_id" = "comment"."user_id" AND "rate" > 50
Join with Raw Object
"[>]account" => Medoo::raw("ON <post.author_id> = <account.user_id>")
LEFT JOIN "account" ON "post"."author_id" = "account"."user_id"
Data Mapping
Customize output data construction - The key name for wrapping data has no relation to columns themselves, and it is multidimensional.
$data = $database->select("post", [ "[>]account" => ["user_id"] ], [ "post.content", "userData" => [ "account.user_id", "account.email", "meta" => [ "account.location", "account.gender" ] ] ], [ "LIMIT" => [0, 2] ]); echo json_encode($data);
[{ content: "Hello world!", userData: { user_id: "1", email: "foo@example.com", meta: { location: "New York", gender: "male" } } }, { content: "Hey everyone", userData: { user_id: "2", email: "bar@example.com", meta: { location: "London", gender: "female" } } }]
Index Mapping
Setting the column as the first key name of the column parameter, the result will be indexed by this name.
$data = $database->select("post", [ "user_id" => [ "nickname", "location", "email" ] ]);
[ 10: { nickname: "foo", location: "New York", email: "foo@example.com" }, 12: { nickname: "bar", location: "New York", email: "bar@medoo.in" } ]
Data Type Declaration
Set the type of output data.
// Supported data type: [String | Bool | Int | Number | Object | JSON] // [String] is the default type for all output data. // [Object] is a PHP object data decoded by serialize(), and will be unserialize() // [JSON] is a valid JSON, and will be json_decode() $data = $database->select("post", [ "[>]account" => ["user_id"] ], [ "post.post_id", "profile" => [ "account.age [Int]", "account.is_locked [Bool]", "account.userData [JSON]" ] ]); echo json_encode($data);
[{ post_id: "1", profile: { age: 20, is_locked: true, userData: ["foo", "bar", "tim"] } }, { post_id: "2", profile: { age: 25, is_locked: false, userData: ["mydata1", "mydata2"] } }]
// Store an object in the database, and get it back. class Foo { var $bar = "cat"; public function __wakeup() { $this->bar = "dog"; } } $object_data = new Foo(); $database->insert("account", [ "data" => $object_data ]); $data = $database->select("account", [ "data [object]" ]); echo $data[0]["data"]->bar; // The object\'s __wakeup function will be called and update the value. // So the output will be "dog". "dog"
Alias
You can use the alias as a new column or table name instead of the original one. This is useful for table joining to prevent name conflict.
$data = $database->select("account", [ "user_id", "nickname (my_nickname)" ]); // $data = array( // [0] => array( // "user_id" => "1", // "my_nickname" => "foo" // ), // [1] => array( // "user_id" => "2", // "my_nickname" => "bar" // ) // ) $data = $database->select("post (content)", [ "[>]account (user)" => "user_id", ], [ "content.user_id (author_id)", "user.user_id" ]); // $data = array( // [0] => array( // "author_id" => "1", // "user_id" => "321" // ), // [1] => array( // "author_id" => "2", // "user_id" => "322" // ) // )
SELECT "content"."user_id" AS author_id, "user"."user_id" FROM "post" AS "content" LEFT JOIN "account" AS "user" USING ("user_id")
Distinct
To add a distinct keyword to the column, you can put @
in front of the column name in any order.
$data = $database->select("account", [ "id", "name", // The location with the @ sign will pop up to the top. "@location" ]);
SELECT DISTINCT "location","id","name" FROM "account"
To get the count number with distinct, you can use it with the raw object.
$data = $database->select("account", [ "unique_locations" => Medoo::raw("COUNT(DISTINCT <location>)") ]);
SELECT COUNT(DISTINCT "location") AS "unique_locations" FROM "account"