ivan tsai
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # Database 與 Doctrine ORM Symfony 提供了在應用程式中使用資料庫所需的所有工具,這要歸功於Doctrine,這是處理資料庫的最佳 PHP libraires。 這些工具支持 MySQL 和 PostgreSQL 等關聯性資料庫以及NoSQL資料庫如MongoDB 。 - 此文件解釋了在 Symfony 應用程式中使用關聯資料庫的推薦方法; - 如果需要低層級訪問權限來對關聯資料庫執行原始的SQL \查詢(類似於 PHP 的PDO),請閱讀[這裡](https://symfony.com/doc/4.4/doctrine/dbal.html) - 如果你使用MongoDB 資料庫,請閱讀[DoctrineMongoDBBundle](https://symfony.com/doc/current/bundles/DoctrineMongoDBBundle/index.html)文件。 ## 安裝 Doctrine 透過```orm```[symfony pack](https://symfony.com/doc/4.4/setup.html#symfony-packs)安裝Doctrine 的相關支援,這將有助於生成一些code: ``` composer require symfony/orm-pack composer require --dev symfony/maker-bundle ``` ## 配置資料庫 資料庫連接資訊存儲為名為```DATABASE+URL```的環境變量。 對於開發環境,你可以在下面找到並客製化這個```.env```: ``` # .env (or override DATABASE_URL in .env.local to avoid committing your changes) # customize this line! DATABASE_URL="mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=5.7" # to use mariadb: DATABASE_URL="mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=mariadb-10.5.8" # to use sqlite: # DATABASE_URL="sqlite:///%kernel.project_dir%/var/app.db" # to use postgresql: # DATABASE_URL="postgresql://db_user:db_password@127.0.0.1:5432/db_name?serverVersion=11&charset=utf8" # to use oracle: # DATABASE_URL="oci8://db_user:db_password@127.0.0.1:1521/db_name" ``` :::danger Caution 如果用戶名稱、密碼、host或資料庫名稱在 URI 中包含任何被視為特殊的符號(例如+, @, $, #, /, :, *, !),必須對它們進行encode。 有關保留關鍵字的完整列表,請參閱[RFC 3986](https://www.ietf.org/rfc/rfc3986.txt),或使用```urlencode```函數對其進行encode。 在這種情況下,需要刪除```resolve:```前綴``` inconfig/packages/doctrine.yaml```以避免錯誤:``` url:'%env(resolve:DATABASE_URL)%'``` ::: 現在連接參數已設置,Doctrine可以透過```db_name```創建你的資料庫: ``` php bin/console doctrine:database:create ``` 透過```config/packages/doctrine.yaml```配置更多選項,包括你的```server_version```(例如,如果使用 MySQL 5.7,則為 5.7),這可能會影響 Doctrine 的功能。 :::success 還有許多其他的 Doctrine 指令。 執行 ```php bin/console list doctrine ```以查看完整列表。 ::: ## 創建entity class 假設你正在構建一個需要"產品(products)"的應用程式。 甚至不用考慮 Doctrine 或資料庫,你需要一個Product object來表示這些產品。 可以使用```make:entity```指令創建此class以及您需要的任何field。 該指令會問你一些問題 - 像下面那樣回答它們: ``` $ php bin/console make:entity Class name of the entity to create or update: > Product New property name (press <return> to stop adding fields): > name Field type (enter ? to see all types) [string]: > string Field length [255]: > 255 Can this field be null in the database (nullable) (yes/no) [no]: > no New property name (press <return> to stop adding fields): > price Field type (enter ? to see all types) [string]: > integer Can this field be null in the database (nullable) (yes/no) [no]: > no New property name (press <return> to stop adding fields): > (press enter again to finish) ``` 現在產生了一個個新```src/Entity/Product.php```文件: ```php= // src/Entity/Product.php namespace App\Entity; use App\Repository\ProductRepository; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity(repositoryClass=ProductRepository::class) */ class Product { /** * @ORM\Id() * @ORM\GeneratedValue() * @ORM\Column(type="integer") */ private $id; /** * @ORM\Column(type="string", length=255) */ private $name; /** * @ORM\Column(type="integer") */ private $price; public function getId(): ?int { return $this->id; } // ... getter and setter methods } ``` >note 困惑為什麼價格是整數(integer)?別擔心:這只是一個例子。 但是,將價格存儲為整數(例如 100 = 1 美元)可以避免四捨五入問題。 >note 如果您使用的是 SQLite 數據庫,您將看到以下錯誤: PDOException: SQLSTATE[HY000]: General error: 1 Cannot add a NOT NULL column with default value NULL。 >向```description```屬性添加```nullable=true```選項以解決問題。 :::danger Caution 在 MySQL 5.6 及更早版本中使用 InnoDB 表時,索引鍵前綴有 767 bytes的限制。 具有 255 個char長度和 utf8mb4 編碼的字串列超過了該限制。 這意味著該類型的任何列```string```,且```unique=true```必須將其最大```length```設定為```190```。 否則,您將看到此錯誤: "[PDOException] SQLSTATE[42000]: Syntax error or access conflict: 1071 Specified key was too long; max key length is 767 bytes"。 ::: 這個class被稱為“實體”。 可以將 Product object 保存和查詢到 product 資料庫的表中。 Product entity 中的每個屬性都可以映射到該表中的一列。 這通常通過註釋```@ORM\...```來完成,可以在每個屬性上方看到的註釋: ![](https://i.imgur.com/V6qh2jg.png) Doctrine 支持多種field類型,每種類型都有自己的選項。 要查看完整列表,請查看Doctrine 的映射(map)類型[文件](https://www.doctrine-project.org/projects/doctrine-orm/en/current/reference/basic-mapping.html)。 如果要使用 XML 而不是註釋,請將```type: xml```和```dir:``` ```'%kernel.project_dir%/config/doctrine'```添加到```config/packages/doctrine.yaml```文件中的entity映射 。 :::danger Caution 注意不要使用保留的 SQL 關鍵字作為table名稱或列名稱(例如GROUP或USER)。有關如何轉譯這些的詳細訊息,請參閱 Doctrine 的[保留 SQL 關鍵字文件](https://www.doctrine-project.org/projects/doctrine-orm/en/current/reference/basic-mapping.html#quoting-reserved-words)。 或者,使用```@ORM\Table(name="groups")```上面的class更改table名稱或使用```name="group_name"```選項配置列名稱。 ::: ## Migrations(遷移):創建資料庫表(tables)/架構(schema) ```Product```class是完全配置好並保存到一個```product```表。 如果你剛剛定義了這個class,你的資料庫實際上還沒有這個```product table。 要添加它,可以利用已經安裝的```DoctrineMigrationsBundle```: ``` php bin/console make:migration ``` 如果一切正常,您應該會看到如下內容: ``` SUCCESS! ``` 下一步: 查看新的Migrations “src/Migrations/Version20180207231217.php” 然後: 使用執行migrations透過 ```bin/console:migrations:migrate``` 打開此文件,它將包含更新資料庫所需的 SQL!要執行該 SQL,請執行你的migrations: ``` php bin/console doctrine:migrations:migrate ``` 此指令執行尚未針對您的資料庫執行的所有migrations文件。 應該在部署你的應用程式時,執行此命令以保持應用程式資料庫是最新的。 ## migrations和添加更多field 如果需要向```Product```中添加一個新的field屬性```description```該怎麼做? 可以編輯class以添加新屬性。 也可以再次使用```make:entity```: ``` $ php bin/console make:entity Class name of the entity to create or update > Product New property name (press <return> to stop adding fields): > description Field type (enter ? to see all types) [string]: > text Can this field be null in the database (nullable) (yes/no) [no]: > no New property name (press <return> to stop adding fields): > (press enter again to finish) ``` 這添加了新的description屬性以及```getDescription()```和```setDescription()```方法: ```php= // src/Entity/Product.php // ... class Product { // ... + /** + * @ORM\Column(type="text") + */ + private $description; // getDescription() & setDescription() were also added } ``` 新屬性已映射,但尚不存在```product```。 此時可以生成新的migrations: ``` php bin/console make:migration ``` 這一次,生成的文件中的 SQL 將如下所示: ``` ALTER TABLE product ADD description LONGTEXT NOT NULL ``` migrations系統是非常聰明的。 它會將所有entities與資料庫的當前狀態進行比較,並生成同步它們所需的 SQL!像以前一樣,執行您的migrations: ``` php bin/console doctrine:migrations:migrate ``` 這只會執行一個新的migration文件,因為 ```DoctrineMigrationsBundle``` 知道第一次migrations已經在之前執行過。在系統背後,它管理一個```migration_versions```talbe來追蹤這一點。 每次對架構進行更改時,執行這兩個指令來生成migrations,然後執行它。 確保在部署時提交migrations文件並執行它們。 :::success 如果你更喜歡手動添加新屬性,該```make:entity```指令可以為你生成 ```getter ```和 ```setter```方法: ``` php bin/console make:entity --regenerate ``` 如果你進行了一些更改並希望重新生成所有getter/setter 方法,也可以通過```--overwrite```此指令來完成. ::: ## 將object持久化(persisting)到資料庫 將```Product```object保存到資料庫了,透過創建一個新的控制器進行實驗: ``` php bin/console make:controller ProductController ``` 在控制器內部,您可以創建一個新Product object ,在其上設置資料並保存: ```php= // src/Controller/ProductController.php namespace App\Controller; // ... use App\Entity\Product; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\HttpFoundation\Response; class ProductController extends AbstractController { /** * @Route("/product", name="create_product") */ public function createProduct(): Response { // you can fetch the EntityManager via $this->getDoctrine() // or you can add an argument to the action: createProduct(EntityManagerInterface $entityManager) $entityManager = $this->getDoctrine()->getManager(); $product = new Product(); $product->setName('Keyboard'); $product->setPrice(1999); $product->setDescription('Ergonomic and stylish!'); // tell Doctrine you want to (eventually) save the Product (no queries yet) $entityManager->persist($product); // actually executes the queries (i.e. the INSERT query) $entityManager->flush(); return new Response('Saved new product with id '.$product->getId()); } } ``` 嘗試訪問 http://localhost:8000/product 恭喜!你剛剛在```product ```table中創建了第一行。 為了證明,可以直接查詢資料庫: ``` php bin/console doctrine:query:sql 'SELECT * FROM product' ``` 更詳細地看一下前面的例子: - 第18行的```$this->getDoctrine()->getManager()```方法獲取Doctrine的entity管理object,它是在Doctrine中最重要的object。 它負責將object保存到資料庫,並從資料庫中獲取object。 - 第 20-23 行,將```product```像任何其他 PHP 的object一樣實例化和使用該object。 - 第26行 ,```persist($product)```呼叫(call)告訴 Doctrine“管理” ```product``` object。 這並不會導致要到資料庫中進行查詢(query)。 - 第29行,```flush()```方法被呼叫時,Doctrine 會查看它正在管理的所有object,看看它們是否需要持久保存到資料庫中。 在這個例子中,```product```object的資料在資料庫中不存在,所以entity管理器執行一個```INSERT```查詢,在product table中創建一個新row。 >note 如果```flush()```呼叫失敗,```Doctrine\ORM\ORMException```則拋出異常。請參閱[Transactions和Concurrency](https://www.doctrine-project.org/projects/doctrine-orm/en/current/reference/transactions-and-concurrency.html)。 無論是在創建還是更新obeject,工作流程總是相同的:Doctrine 足夠聰明,可以知道它是否應該插入或更新entity。 ## 驗證對象 Symfony 驗證器會重新使用 Doctrine metadata來執行一些基本的驗證任務: ```php= // src/Controller/ProductController.php namespace App\Controller; use App\Entity\Product; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Validator\Validator\ValidatorInterface; // ... class ProductController extends AbstractController { /** * @Route("/product", name="create_product") */ public function createProduct(ValidatorInterface $validator): Response { $product = new Product(); // This will trigger an error: the column isn't nullable in the database $product->setName(null); // This will trigger a type mismatch error: an integer is expected $product->setPrice('1999'); // ... $errors = $validator->validate($product); if (count($errors) > 0) { return new Response((string) $errors, 400); } // ... } } ``` 儘管```Product```entity 沒有定義任何明顯的驗證配置,Symfony 會在 Doctrine 映射配置來推斷一些驗證規則。 例如,假設該```name```屬性在資料庫中不能為```null```,一個 NotNull 約束會自動添加到該屬性中(如果它不包含該約束)。 下表總結了 Doctrine metadata 和 Symfony 自動添加的相應驗證約束之間的映射: |doctrine屬性 |驗證約束(validation constraint)| notes| |---|---|---| |```nullable=false ```|[NotNull](https://symfony.com/doc/4.4/reference/constraints/NotNull.html)| [需要安裝PropertyInfo 組件](https://symfony.com/doc/4.4/components/property_info.html)| |```type```| [Type](https://symfony.com/doc/4.4/reference/constraints/Type.html) |[需要安裝PropertyInfo 組件](https://symfony.com/doc/4.4/components/property_info.html)| |```unique=true``` |[UniqueEntity](https://symfony.com/doc/4.4/reference/constraints/UniqueEntity.html) |```length``` |[Length](https://symfony.com/doc/4.4/reference/constraints/Length.html) | 因為[Form 組件](https://symfony.com/doc/4.4/forms.html)和[API Platform](https://api-platform.com/docs/core/validation/) 在內部使用 Validator 組件,所以您的所有表單和 Web API 也將自動受益於這些自動驗證約束。 這種自動驗證是一個很好的功能,可以提高您的工作效率,但它並不能完全取代驗證配置。 您仍然需要添加一些驗證約束以確保用戶提供的資料是正確的。 ## 從資料庫中獲取object 從資料庫中取回object更容易。假設您希望能夠去```/product/1```查看您的新產品: ```php= // src/Controller/ProductController.php namespace App\Controller; use App\Entity\Product; use Symfony\Component\HttpFoundation\Response; // ... class ProductController extends AbstractController { /** * @Route("/product/{id}", name="product_show") */ public function show(int $id): Response { $product = $this->getDoctrine() ->getRepository(Product::class) ->find($id); if (!$product) { throw $this->createNotFoundException( 'No product found for id '.$id ); } return new Response('Check out this great product: '.$product->getName()); // or render a template // in the template, print things with {{ product.name }} // return $this->render('product/show.html.twig', ['product' => $product]); } } ``` 另一種可能性是利用```ProductRepository```來使用 Symfony 的自動裝配功能並由依賴注入(injected by the dependency)來注入容器: ```php= // src/Controller/ProductController.php namespace App\Controller; use App\Entity\Product; use App\Repository\ProductRepository; use Symfony\Component\HttpFoundation\Response; // ... class ProductController extends AbstractController { /** * @Route("/product/{id}", name="product_show") */ public function show(int $id, ProductRepository $productRepository): Response { $product = $productRepository ->find($id); // ... } } ``` 嘗試訪問! http://localhost:8000/product/1 當您查詢特定類型的object時,總是使用所謂的“存儲庫(repository)”。可以將存儲庫視為一個 PHP class,它的唯一工作是幫助獲取某個class的entity。 一旦你有了一個存儲庫object,你就有了許多輔助方法: ```php= $repository = $this->getDoctrine()->getRepository(Product::class); // look for a single Product by its primary key (usually "id") $product = $repository->find($id); // look for a single Product by name $product = $repository->findOneBy(['name' => 'Keyboard']); // or find by name and price $product = $repository->findOneBy([ 'name' => 'Keyboard', 'price' => 1999, ]); // look for multiple Product objects matching the name, ordered by price $products = $repository->findBy( ['name' => 'Keyboard'], ['price' => 'ASC'] ); // look for *all* Product objects $products = $repository->findAll(); ``` 您還可以為更複雜的查詢添加自定義方法!稍後將在資料庫和 Doctrine ORM部分詳細介紹。 :::success 渲染 HTML 頁面時,頁面底部的 Web debug工具欄將顯示查詢的數量和執行它們所花費的時間: ![](https://i.imgur.com/hUD3dkD.png) 如果資料庫查詢次數過多,該按鍵將變為黃色,表示某些內容可能不正確。 點擊該按鍵以打開 Symfony Profiler 並查看已執行的確切查詢。 如果您沒有看到網頁debug工具,安裝profiler Symfony的[工具](https://symfony.com/doc/4.4/setup.html#symfony-packs)並且執行以下命令:```composer require --dev symfony/profiler-pack```。 ::: ## 自動獲取object (ParamConverter) 在很多情況下,您可以使用[SensioFrameworkExtraBundle](https://symfony.com/bundles/SensioFrameworkExtraBundle/current/index.html)自動為您做查詢,可以透過以下指令安裝 ``` composer require sensio/framework-extra-bundle ``` 現在,簡化你的控制器: ```php= // src/Controller/ProductController.php namespace App\Controller; use App\Entity\Product; use App\Repository\ProductRepository; use Symfony\Component\HttpFoundation\Response; // ... class ProductController extends AbstractController { /** * @Route("/product/{id}", name="product_show") */ public function show(Product $product): Response { // use the Product! // ... } } ``` bundle所使用的```{id}```是來自於路由的查詢來自於```Product```的```id```column。 如果未找到,則會生成 404 頁面。 您可以使用更多選項。 閱讀有關[ParamConverter](https://symfony.com/bundles/SensioFrameworkExtraBundle/current/annotations/converters.html)的文件。 ## 更新obeject 一旦你從 Doctrine 獲取了一個object,就可以像與任何 PHP model一樣與它進行溝通: ```php= // src/Controller/ProductController.php namespace App\Controller; use App\Entity\Product; use App\Repository\ProductRepository; use Symfony\Component\HttpFoundation\Response; // ... class ProductController extends AbstractController { /** * @Route("/product/edit/{id}") */ public function update(int $id): Response { $entityManager = $this->getDoctrine()->getManager(); $product = $entityManager->getRepository(Product::class)->find($id); if (!$product) { throw $this->createNotFoundException( 'No product found for id '.$id ); } $product->setName('New product name!'); $entityManager->flush(); return $this->redirectToRoute('product_show', [ 'id' => $product->getId() ]); } } ``` 使用 Doctrine 編輯現有product包括三個步驟: 1. 從 Doctrine 中獲取對象; 2. 修改對象; 3. 呼叫```flush()```entity管理器。 可以呼叫```$entityManager->persist($product)```,但這不是必需的:Doctrine 已經在“觀察”您的object的變化。 ## 刪除object 需要呼叫```remove()``` entity管理器的方法: ```php= $entityManager->remove($product); $entityManager->flush(); ``` 該```remove()```方法通知 Doctrine 您想從資料庫中刪除指定的object。在呼叫```DELETE```查詢在呼叫```flush()```方法前,不會實際執行查詢。 ## 查詢對象:存儲庫(repository) 您已經看到存儲庫object如何讓你無需任何動作即可運行基本查詢: ```php= // from inside a controller $repository = $this->getDoctrine()->getRepository(Product::class); $product = $repository->find($id); ``` 但是,如果需要更複雜的查詢怎麼辦?當您使用```make:entity```生成entity時,該命令還生成了一個```ProductRepository```class: ```php= // src/Repository/ProductRepository.php namespace App\Repository; use App\Entity\Product; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Persistence\ManagerRegistry; class ProductRepository extends ServiceEntityRepository { public function __construct(ManagerRegistry $registry) { parent::__construct($registry, Product::class); } } ``` 當您獲取存儲庫(即```->getRepository(Product::class)```)時,它 實際上是該object的一個實例!這是因為```repositoryClass```在```Product```entity class頂部生成的配置。 假設您要查詢大於某個價格的所有```Product```object。 向你的存儲庫添加一個新方法: ```php= // src/Repository/ProductRepository.php // ... class ProductRepository extends ServiceEntityRepository { public function __construct(ManagerRegistry $registry) { parent::__construct($registry, Product::class); } /** * @return Product[] */ public function findAllGreaterThanPrice(int $price): array { $entityManager = $this->getEntityManager(); $query = $entityManager->createQuery( 'SELECT p FROM App\Entity\Product p WHERE p.price > :price ORDER BY p.price ASC' )->setParameter('price', $price); // returns an array of Product objects return $query->getResult(); } } ``` 傳遞給的字串```createQuery()```可能看起來像 SQL,但它是 Doctrine Query Language。 這允許你使用一般的的查詢語言(query language)來輸入查詢,但改為引用 PHP object來取代(即在```FROM```語句中)。 現在,您可以在存儲庫上呼叫此方法: ```php= // from inside a controller $minPrice = 1000; $products = $this->getDoctrine() ->getRepository(Product::class) ->findAllGreaterThanPrice($minPrice); // ... ``` 有關如何將存儲庫注入任何服務的資訊,請參閱[service container](https://symfony.com/doc/4.4/service_container.html#services-constructor-injection)。 ### 使用查詢生成器(query builder)查詢 Doctrine 還提供了一個[Query Builder](https://www.doctrine-project.org/projects/doctrine-orm/en/current/reference/query-builder.html),一種針對物件導向的查詢方式。 建議在動態構建查詢時使用(基於PHP條件的情況下): ```php= // src/Repository/ProductRepository.php // ... class ProductRepository extends ServiceEntityRepository { public function findAllGreaterThanPrice(int $price, bool $includeUnavailableProducts = false): array { // automatically knows to select Products // the "p" is an alias you'll use in the rest of the query $qb = $this->createQueryBuilder('p') ->where('p.price > :price') ->setParameter('price', $price) ->orderBy('p.price', 'ASC'); if (!$includeUnavailableProducts) { $qb->andWhere('p.available = TRUE'); } $query = $qb->getQuery(); return $query->execute(); // to get just one result: // $product = $query->setMaxResults(1)->getOneOrNullResult(); } } ``` ### 使用 SQL 查詢 另外,如果需要,可以直接用SQL查詢: ```php= // src/Repository/ProductRepository.php // ... class ProductRepository extends ServiceEntityRepository { public function findAllGreaterThanPrice(int $price): array { $conn = $this->getEntityManager()->getConnection(); $sql = ' SELECT * FROM product p WHERE p.price > :price ORDER BY p.price ASC '; $stmt = $conn->prepare($sql); $stmt->execute(['price' => $price]); // returns an array of arrays (i.e. a raw data set) return $stmt->fetchAllAssociative(); } } ``` 使用 SQL,您將回傳原始資料,而不是object(除非您使用[NativeQuery](https://www.doctrine-project.org/projects/doctrine-orm/en/current/reference/native-sql.html)功能)。 ## 配置 請參閱[Doctrine配置](https://symfony.com/doc/4.4/reference/configuration/doctrine.html)參考。 ## 關係(relationships)和關聯(associations) Doctrine 提供了管理數據庫關係(也稱為關聯)所需的所有功能,包括 ManyToOne、OneToMany、OneToOne 和 ManyToMany 關係。 相關資訊,請參閱此[文件](https://symfony.com/doc/4.4/doctrine/associations.html)。 ## 資料庫測試 閱讀此[文件](https://symfony.com/doc/4.4/testing/database.html)。

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully