|
5 | 5 | - [Defining and Creating Model Objects](#defining-and-creating-model-objects) |
6 | 6 | - [Using a Factory Function to Instantiate & Retrieve Models](#using-a-factory-function-to-instantiate-and-retrieve-models) |
7 | 7 | - [Creating Records & Inserting Data into the Database](#creating-records--inserting-data-into-the-database) |
| 8 | + - [Deleting Data](#deleting-data) |
| 9 | + - [Updating Data](#updating-data) |
8 | 10 |
|
9 | 11 |
|
10 | 12 | ## Design Considerations |
@@ -388,5 +390,217 @@ $allSuccessfullyInserted = $authorsModel->insertMany( |
388 | 390 | //////////////////////////////////////////////////////////////////////////////// |
389 | 391 | ``` |
390 | 392 |
|
| 393 | +## Deleting Data |
| 394 | + |
| 395 | +There are four ways of deleting data from the database: |
| 396 | + |
| 397 | +1. By fetching one or more existing records from the database into record objects and then calling the **delete** method on each Record object (NOTE: the data is deleted from the database but the Record object still contains the data and is automatically marked as new. To make sure the data is both deleted from the database and cleared out of the Record object the **delete** method on the Record object must be called with a boolean value of **true** as its first parameter). |
| 398 | + |
| 399 | +2. By fetching one or more existing records from the database into record objects stored in a Collection object, and then calling the **deleteAll** method on the Collection object. This will cause all the records in the collection to be deleted from the database, but the Record objects will still be in the Collection object with their data intact. **removeAll** should additionally be called on the Collection object to remove the Record objects from the Collection object. |
| 400 | + |
| 401 | +3. By calling the **deleteMatchingDbTableRows** method on a Model object. This method does not involve the retrieval of Record objects, rather only the conditions for matching the rows of data in the database table to be deleted needs to be supplied to **deleteMatchingDbTableRows**. It accepts an associative array whose keys should be the names of the database table column names & whose values are the values to use in an equality test to match against the corresponding database column names. If you need more fine grained criteria other than an equality test to match records that need to be deleted, you should consider the fourth option below. |
| 402 | + |
| 403 | + >Note: there is also a **deleteSpecifiedRecord** method in the Model class which accepts a Record object as parameter and deletes the database row associated with the Record object, sets the primary key value of the Record object to null if the primary key field is auto-incrementing and also sets the **is_new** property of the Record object to the boolean value of true (NOTE: it does not clear all the other data in the Record object). The **deleteSpecifiedRecord** method does not really need to be called, since the delete method in the Record class calls it internally when **delete** is called on a Record object that needs to be deleted. |
| 404 | +
|
| 405 | +4. By using the **PDO** object returned by the **getPDO** method of the Model class to execute a **DELETE** SQL query directly on the database or using the **runQuery** method of the instance of **\LeanOrm\DBConnector** returned by the **getDbConnector** method of the Model class. You need to be very careful to make sure your deletion query targets the exact records you want to delete so that you don't accidentally delete data that should not be deleted. |
| 406 | + |
| 407 | +> **NOTE:** You can use the Record class' **delete** method & the Collection class' **deleteAll** & **removeAll** methods to also delete fetched related data. |
| 408 | +
|
| 409 | +Below are some code samples demonstrating how to delete data: |
| 410 | + |
| 411 | +```php |
| 412 | +<?php |
| 413 | +$authorsModel = new AuthorsModel('mysql:host=hostname;dbname=blog', 'user', 'pwd'); |
| 414 | + |
| 415 | +// first insert 6 records into the authors table |
| 416 | + $authorsModel->insertMany( |
| 417 | + [ |
| 418 | + ['name' => 'Joe Blow'], |
| 419 | + ['name' => 'Jill Blow'], |
| 420 | + ['name' => 'Jack Doe'], |
| 421 | + ['name' => 'Jane Doe'], |
| 422 | + ['name' => 'Jack Bauer'], |
| 423 | + ['name' => 'Jane Bauer'], |
| 424 | + ] |
| 425 | +); |
| 426 | + |
| 427 | +/////////////////////////////////////////////////////////////////// |
| 428 | +$joeBlowRecord = $authorsModel->fetchOneRecord( |
| 429 | + $authorsModel->getSelect() |
| 430 | + ->where(' name = :name_val ', [ 'name_val' => 'Joe Blow']) |
| 431 | + ); |
| 432 | +// - Deletes record from the database table |
| 433 | +// - Flags the record object as new |
| 434 | +// - Clears related data associated with the record object |
| 435 | +// - (does not delete them from the database) |
| 436 | +// - Removes the primary key field from the record object, |
| 437 | +// - if it's an auto-incrementing field in the database table |
| 438 | +// - Other remaining data in the record remains |
| 439 | +$joeBlowRecord->delete(false); |
| 440 | + |
| 441 | +/////////////////////////////////////////////////////////////////// |
| 442 | +$jillBlowRecord = $authorsModel->fetchOneRecord( |
| 443 | + $authorsModel->getSelect() |
| 444 | + ->where(' name = :name_val ', [ 'name_val' => 'Jill Blow']) |
| 445 | + ); |
| 446 | +// - Deletes record from the database table |
| 447 | +// - Flags the record object as new |
| 448 | +// - Clears all data associated with the record object |
| 449 | +$jillBlowRecord->delete(true); |
| 450 | + |
| 451 | +/////////////////////////////////////////////////////////////////// |
| 452 | +$jackAndJaneDoe = $authorsModel->fetchRecordsIntoCollection( |
| 453 | + $authorsModel->getSelect() |
| 454 | + ->where( |
| 455 | + ' name IN (:bar) ', // named paceholder for WHERE IN |
| 456 | + [ 'bar' => [ 'Jack Doe', 'Jane Doe' ]] |
| 457 | + ) |
| 458 | + ); |
| 459 | + |
| 460 | +// - Delete records from the database |
| 461 | +// - Flags each record object as new |
| 462 | +// - Clears related data associated with each record object |
| 463 | +// - (does not delete them from the database) |
| 464 | +// - Removes the primary key field from each record object, |
| 465 | +// - if it's an auto-incrementing field in the database table |
| 466 | +// - Other remaining data in each record remains |
| 467 | +// - Record objects remain in the collection |
| 468 | +$jackAndJaneDoe->deleteAll(); |
| 469 | + |
| 470 | +// Removes all the record objects from the collection object |
| 471 | +// If those record objects are not referenced via any other variable, |
| 472 | +// they will be garbage collected when next PHP's garbage collection |
| 473 | +// mechanism kicks in. |
| 474 | +$jackAndJaneDoe->removeAll(); |
| 475 | + |
| 476 | +/////////////////////////////////////////////////////////////////// |
| 477 | + |
| 478 | +// Generates and executes the sql query below: |
| 479 | +// DELETE from authors where name in ('Jack Bauer', 'Jane Bauer'); |
| 480 | +$authorsModel->deleteMatchingDbTableRows( |
| 481 | + [ |
| 482 | + 'name' => ['Jack Bauer', 'Jane Bauer'] |
| 483 | + ] |
| 484 | + ); |
| 485 | + |
| 486 | +/////////////////////////////////////////////////////////////////// |
| 487 | + |
| 488 | +// For more complicated DELETE queries, use the PDO object |
| 489 | +$pdo = $authorsModel->getPDO(); |
| 490 | +$data = ['start'=> '2022-12-31 21:10:20', 'end' => '2022-12-31 21:08:20']; |
| 491 | +$sql = "DELETE FROM authors WHERE date_created < :start AND m_timestamp < :end"; |
| 492 | +$pdo->prepare($sql)->execute($data); |
| 493 | + |
| 494 | +/////////////////////////////////////////////////////////////////// |
| 495 | +// The code below does the exact same thing as the PDO code above |
| 496 | +$dbConnector = $authorsModel->getDbConnector(); |
| 497 | +// passing $authorsModel as the last argument is optional and only |
| 498 | +// useful if you have query logging enabled and you want this query |
| 499 | +// to be added to the query log entries for $authorsModel |
| 500 | +$dbConnector->runQuery($sql, $data, $authorsModel); |
| 501 | +``` |
| 502 | +## Updating Data |
| 503 | + |
| 504 | +These are the ways of updating data in the database: |
| 505 | + |
| 506 | +1. By fetching one or more existing records, modifying them & calling either the **save** or **saveInTransaction** method on each record. |
| 507 | + |
| 508 | +2. By fetching one or more records into a Collection object, modifying those record objects contained in the collection & then calling the **saveAll** method on the collection object. |
| 509 | + |
| 510 | +3. By fetching one or more records & calling the Model class' **updateSpecifiedRecord** method on each record. The Record class' **save** methods actually use **updateSpecifiedRecord** under the hood to save existing records, so you really should not need to be using the Model class' **updateSpecifiedRecord** method to update existing records. |
| 511 | + |
| 512 | +4. By calling the Model class' **updateMatchingDbTableRows** method on any instance of the Model class. This method does not retrieve existing records from the database, it only generates & executes a SQL UPDATE statement with some equality criteria (e.g. WHERE colname = someval or colname in (val1,...,valN) or colname IS NULL) based on the arguments supplied to the method. |
| 513 | + |
| 514 | +5. By using the **PDO** object returned by the **getPDO** method of the Model class to execute an **UPDATE** SQL query directly on the database or using the **runQuery** method of the instance of **\LeanOrm\DBConnector** returned by the **getDbConnector** method of the Model class. You need to be very careful to make sure your **UPDATE** query targets the exact records you want to update so that you don't accidentally update data that should not be updated. |
| 515 | + |
| 516 | +Below are some code samples demonstrating how to update data: |
| 517 | + |
| 518 | +```php |
| 519 | +<?php |
| 520 | +$authorsModel = new AuthorsModel('mysql:host=hostname;dbname=blog', 'user', 'pwd'); |
| 521 | + |
| 522 | + |
| 523 | +// first insert 6 records into the authors table |
| 524 | + $authorsModel->insertMany( |
| 525 | + [ |
| 526 | + ['name' => 'Joe Blow'], |
| 527 | + ['name' => 'Jill Blow'], |
| 528 | + ['name' => 'Jack Doe'], |
| 529 | + ['name' => 'Jane Doe'], |
| 530 | + ['name' => 'Jack Bauer'], |
| 531 | + ['name' => 'Jane Bauer'], |
| 532 | + ] |
| 533 | +); |
| 534 | + |
| 535 | +/////////////////////////////////////////////////////////////////// |
| 536 | +$joeBlowRecord = $authorsModel->fetchOneRecord( |
| 537 | + $authorsModel->getSelect() |
| 538 | + ->where(' name = :name_val ', ['name_val' => 'Joe Blow']) |
| 539 | + ); |
| 540 | + |
| 541 | +// Prepend a title to Joe Blow's name |
| 542 | +$joeBlowRecord->name = 'Mr. ' . $joeBlowRecord->name; |
| 543 | +$joeBlowRecord->save(); // update the record |
| 544 | + |
| 545 | +/////////////////////////////////////////////////////////////////// |
| 546 | +$jackAndJaneDoe = $authorsModel->fetchRecordsIntoCollection( |
| 547 | + $authorsModel->getSelect() |
| 548 | + ->where( |
| 549 | + ' name IN (:bar) ', |
| 550 | + [ 'bar' => ['Jack Doe', 'Jane Doe'] ] |
| 551 | + ) |
| 552 | + ); |
| 553 | + |
| 554 | +foreach ($jackAndJaneDoe as $record){ |
| 555 | + |
| 556 | + // reverse the name of each record |
| 557 | + $record->name = strrev($record->name); |
| 558 | +} |
| 559 | + |
| 560 | +// update all the modified records in the collection |
| 561 | +$jackAndJaneDoe->saveAll(); |
| 562 | + |
| 563 | +/////////////////////////////////////////////////////////////////// |
| 564 | +$jillBlowRecord = $authorsModel->fetchOneRecord( |
| 565 | + $authorsModel->getSelect() |
| 566 | + ->where(' name = :name_val ', ['name_val' => 'Jill Blow']) |
| 567 | + ); |
| 568 | + |
| 569 | +// reverse the name for this record |
| 570 | +$jillBlowRecord->name = strrev($jillBlowRecord->name); |
| 571 | + |
| 572 | +// update the record |
| 573 | +$authorsModel->updateSpecifiedRecord($jillBlowRecord); |
| 574 | + |
| 575 | +/////////////////////////////////////////////////////////////////// |
| 576 | + |
| 577 | +// Generates and executes the sql query below: |
| 578 | +// UPDATE authors set date_created = '20 minutes before now' where name in ('Jack Bauer', 'Jane Bauer'); |
| 579 | +$authorsModel->updateMatchingDbTableRows( |
| 580 | + [ |
| 581 | + 'date_created' => date('Y-m-d H:i:s', strtotime("-20 minutes")) |
| 582 | + ], |
| 583 | + [ |
| 584 | + 'name' => ['Jack Bauer', 'Jane Bauer'] |
| 585 | + ] |
| 586 | + ); |
| 587 | + |
| 588 | +/////////////////////////////////////////////////////////////////// |
| 589 | + |
| 590 | +// For more complicated UPDATE queries, use the PDO object |
| 591 | +$pdo = $authorsModel->getPDO(); |
| 592 | +$data = ['start'=> '2022-12-31 21:10:20', 'end' => '2022-12-31 21:08:20']; |
| 593 | +$sql = "UPDATE authors SET name = CONCAT(author_id, '-', name) WHERE date_created < :start AND m_timestamp < :end"; |
| 594 | +$pdo->prepare($sql)->execute($data); |
| 595 | + |
| 596 | +/////////////////////////////////////////////////////////////////// |
| 597 | +// The code below does the exact same thing as the PDO code above |
| 598 | +$dbConnector = $authorsModel->getDbConnector(); |
| 599 | +// passing $authorsModel as the last argument is optional and only |
| 600 | +// useful if you have query logging enabled and you want this query |
| 601 | +// to be added to the query log entries for $authorsModel |
| 602 | +$dbConnector->runQuery($sql, $data, $authorsModel); |
| 603 | +``` |
| 604 | + |
391 | 605 |
|
392 | 606 | [<<< Previous](./indtroduction.md) | [Next >>>](./more-about-models.md) |
0 commit comments