17.12.20205 min

Zdzisław Bronikowski

Aplikacja w Yii2 z użyciem Active Record w PHP

Sprawdź, jak stworzyć prostą aplikację we frameworku Yii2 języka PHP, wykorzystując do tego klasę Active Record.

Aplikacja w Yii2 z użyciem Active Record w PHP

Istnieje wiele narzędzi do opisu rzeczywistości i dostarczenia wymaganych usług, które może wykorzystać programista, aby zrealizować postawione przed nim zadania. Wyobraźmy sobie, że mamy wykonać aplikację na początek dostarczającą informacji dotyczących studentów oraz wykładowców wraz z wykładanymi przedmiotami. W dalszej części możemy zastanowić się nad planem zajęć. Zadanie samo w sobie nie jest zbyt skomplikowane, ale pozwoli nam w jakiejś mierze zapoznać się działaniem interesującej nas technologii.

Wracając do naszej aplikacji, w pierwszej kolejności będziemy chcieli przy jej pomocy realizować następujące zadania:

  • Wyświetlić posortowaną listę studentów
  • Wyświetlić listę przedmiotów wraz z wykładowcą
  • Uzyskać listę wykładowców oraz ich dane kontaktowe
  • Wyszukać wszystkie oceny wybranego studenta
  • Obliczyć średnią ocen wybranego studenta
  • Obliczyć średnie wszystkich studentów oraz je posortować


Aby zrealizować wyżej wymienione cele, posłużymy się bazą danych MySQL, frameworkiem Yii2 oraz klasą Active Record, która została stworzona w celu zapewnienia wygodnego dostępu oraz manipulacji danymi znajdującymi się w bazie danych (kod aplikacji na GitHubie). Jest ona oparta na wzorcu projektowym noszącym tę samą nazwę. Jak opisano to w dokumentacji:

“Klasa typu Active Record jest powiązana z tabelą bazodanową, a instacja tej klasy odpowiada pojedynczemu wierszowi w tabeli - atrybut obiektu Active Record reprezentuje wartość konkretnej kolumny w tym wierszu”.

Zanim zaimplementujemy nasze rozwiązania we frameworku, musimy zwrócić uwagę na bazę danych. Na początku będziemy mieli w niej cztery tabele. Pierwsza zawierająca dane studentów, następne w kolejności dane wykładowców, przedmioty oraz oceny końcowe studentów (zrzut bazy w pliku dump- ..).

Tabela students

Teraz możemy zrealizować nasze pierwsze zapytanie do bazy danych:

SELECT * FROM students ORDER BY last_name ASC;


W pierwszym kroku tworzymy model o nazwie Students, który będzie rozszerzeniem klasy Active Record (\yii\db\ActiveRecord), która z kolei jest rozszerzeniem klasy Model. Skutkuje to tym, że wszystkie publiczne metody dostępne w klasie Model możemy wykorzystać w naszej klasie. Plik umieszczamy w sekcji przeznaczonej na modele (models/Students.php).

Na razie w naszym modelu będziemy mieli niewiele oprócz metody tableName, która zwróci nazwę tabeli w bazie danych, z którą dany model jest związany.

namespace app\models;
use Yii;

class Students extends \yii\db\ActiveRecord{

public static function tableName() {

        return '{{students}}';
}
}


W drugim kroku tworzymy kontroler (controllers/StudentsController.php). Nasze zapytanie do bazy danych postawione na początku będzie teraz wyglądało tak:

Students::find()->orderBy('last_name ASC')->all().


Korzystamy tutaj z metody find(), która zwróci obiekt typu ActiveQuery, dzięki któremu możemy pobrać interesujące nas dane. W tym przypadku przez zastosowanie metody orderBy() dane są posortowane. Następnie przy pomocy tablicy $students przekazujemy uzyskane dane do widoku.

namespace app\controllers;

use Yii;
use yii\web\Controller;
use app\models\Students;


class StudentsController extends Controller{
    
    public function actionIndex() {
        
        $students = Students::find()->orderBy('last_name ASC')->all();

        return $this->render('index',['students'=>$students,]);
    }
}


W następnym kroku tworzymy widok (views/students/index.php), gdzie dane przepuszczamy przez pętlę foreach, tworząc w ten sposób tabelę.

Nie jest to jednak koniec naszej pracy. Przy pomocy uzyskanej listy chcemy teraz pobierać informacje dotyczące poszczególnych osób. Wiersz przedstawiony poniżej zmienimy na link odwołujący się do akcji one, która będzie odpowiedzialna za pozyskanie danych dotyczących wybranej osoby.

<td><?php echo $st['last_name'] ?></td>


Teraz wiersz uzyskuje taką postać:

<td><?php echo Html::a($st['last_name'], Url::to(['students/one','id'=>$st['id']]) )?></td>


Aby nasz link działał, musimy jeszcze podłączyć do widoku dwie klasy" Html oraz Url.

use yii\helpers\Url;
use yii\helpers\Html;


Ostatecznie nasza tabela zawierające dane studentów wygląda tak:

Prezentacja danych studentów

Pierwsza część zadania została zrealizowana. Teraz chcemy, aby po kliknięciu w link pokazały się dalsze informacje. Musimy odwołać się do tabel students, grades zawierającej oceny studentów oraz tabeli subjects z nazwami przedmiotów, a konkretniej zrealizować takie zapytania, jak:

SELECT grade FROM grades WHERE id_st = id;
SELECT * FROM subjects;
SELECT * FROM students WHERE id =id;
SELECT COUNT(grade) FROM grades WHERE id_st=id;


Tabela grades

Tabela subjects

Nasza aplikacja musi połączyć dane z wyżej wymienionych tabel. Nie trudno zauważyć, że zachodzą między nimi pewne relacje. ActiveRecord dostarcza wsparcia w pracy z relacjami między tabelami bazy, udostępniając dwie metody: hasOne i hasMany. Jak można się domyśleć, metoda hasOne zwraca jeden powiązany rekord, a hasMany - wiele.

W naszym przypadku, kiedy rozpatrujemy poszczególne przypadki, zauważamy, że tabela grades i students jest powiązana przez identyfikator studenta (id_st), oraz możemy stwierdzić, że zachodzi relacja jeden do wielu, czyli jeden student może posiadać wiele ocen. Możemy więc w modelu Students zastosować metodę hasMany. Będzie ona wyglądała następująco:

public function getGrades() {
        
        return $this->hasMany(Grades::className(), ['id_st'=>'id']);
}


Gdzie id_st odpowiada identyfikatorowi studenta z tabeli grades, a id identyfikatorowi studenta z tabeli students. W kontrolerze wywołamy tą metodę przez użycie nazwy grades. Dokładnie w taki sposób, jak poniżej:

$student = Students::findOne($id);
$marks = $student->grades;


Po wykonaniu wszystkich zapytań, możemy uzyskać widok jak poniżej.

Prezentacja danych wybranego studenta

Metodę hasOne możemy wykorzystać przy prezentacji przedmiotów wraz z wykładowcami. Bierzemy tutaj pod uwagę dwie tabele: lecturers oraz subjects, które są powiązane przez identyfikator wykładowcy (id_lec). W modelu (model/Subjects.php) dopisujemy metodę:

public function getLecturer() {
        
        return $this->hasOne(Lecturers::className(), ['id_lec'=>'id_lec']);
    }


Natomiast w kontrolerze (controllers/SubjectsController.php) w akcji index wywołujemy metodę find() z metodą lecturer.

$subjects = Subjects::find()->with('lecturer')->orderBy('name')->all();


Dodanie metody with() spowoduje, że na podstawie listy przedmiotów uzyskanej przez:

SELECT * FROM subjects;


Zostanie wykonane nastepujące zapytanie:

SELECT * FROM lecturers WHERE id_lec IN (wyniki z poprzedniego zapytania);


Ostatecznie do widoku przekazujemy dane przez tablicę $subjects. We wcześniejszych rozwiązaniach, aby wyłowić interesujące nas dane, musieliśmy porównywać dwie tablice. Teraz nie jest to konieczne.

<?php foreach($subjects as $su) {?>
    <?php $lecturer = $su->lecturer; ?>
    <tr>
        <th scope="row"><?php echo $l; ?></th>
        <td><?php echo $su['name'] ?></td>
        <td><?php echo $lecturer['name'].' '.$lecturer['last_name'] ?></td>
</tr>


Przedmioty wraz z wykładowcami

W pozostałych elementach naszej aplikacji możemy skorzystać z poznanych już metod.

Średnie ocen studentów

Prezentacja danych wykladowców

Każdy z wyżej wymienionych celów aplikacji został tutaj zrealizowany. Należy jednak podkreślić, że jeżeli chodzi o Active Record, nie jest to nawet czubek góry lodowej, a aplikacja również nie posiada na razie możliwości wprowadzania danych. Mogliśmy jednak przekonać się, ze praca z Active Record może być łatwa i przyjemna.

Dodatkowym atutem Active Record może być wspieranie wielu baz danych, co nie wymusza zmiany kodu przy zastosowaniu innej bazy danych.

<p>Loading...</p>

Powiązane artykuły

Dziel się wiedzą ze 160 tysiącami naszych czytelników

Zostań autorem Readme

Accenture Polska

PHP/Magento Developer

medium

Brak widełek

Kontrakt B2BUmowa o pracę

Praca zdalna 100%

Ważna do 27.02.2022

Bardzo dobrze
PHPGIT
Dobrze
Magento 2SOAP/REST HTML/CSS
Początkujący
JSONJavaScript jQuery

Amsterdam Standard Sp. z o.o.

PHP Developer

medium

10 000 - 16 000 PLN

Kontrakt B2BUmowa o pracę

Praca zdalna 100%

Ważna do 13.03.2022

Bardzo dobrze
PHPSymfony
Dobrze
JavaScriptTypeScriptVueJS

Mikronika

PHP Tech Lead

senior

Brak widełek

Kontrakt B2BUmowa o pracę

Praca zdalna 100%

Ważna do 25.02.2022

Bardzo dobrze
PHPSQLMySQL

Polcode Sp. z o.o.

PHP Full Stack Developer

medium

7 500 - 16 000 PLN

Kontrakt B2BUmowa o pracę

Praca zdalna 100%

Ważna do 24.02.2022

Bardzo dobrze
PHP
Dobrze
Symfony / LaravelReact / Vue / AngularJavaScript

Miinto

Tech Manager - PHP (remote)

senior

20 000 - 28 000 PLN

Kontrakt B2BUmowa o pracę

Praca zdalna 100%

Ważna do 11.03.2022

Dobrze
PHP

Miinto

Senior Backend Developer - PHP (remote)

senior

20 000 - 25 000 PLN

Kontrakt B2BUmowa o pracę

Praca zdalna 100%

Ważna do 11.03.2022

Dobrze
PHP

nazwa.pl

Webmaster

junior

Brak widełek

Kontrakt B2BUmowa o pracę

Kraków

Praca zdalna 100%

Ważna do 23.02.2022

Dobrze
PHPJavaScriptWordpress
Początkujący
CSSPrestaShopJoomla

Polcode Sp. z o.o.

Magento Developer

medium

11 000 - 17 000 PLN

Kontrakt B2BUmowa o pracę

Praca zdalna 100%

Ważna do 23.02.2022

Bardzo dobrze
MagentoPHPMySQL
Początkujący
JavaScript

eSky.pl S.A.

FullStack Developer (PHP, Angular)

medium

13 000 - 17 000 PLN

Kontrakt B2B

Katowice

Praca zdalna 100%

Ważna do 17.02.2022

Dobrze
PHPJavaScriptES6

nazwa.pl

Programista PHP

medium

Brak widełek

Kontrakt B2BUmowa o pracę

Kraków

Ważna do 17.02.2022

Bardzo dobrze
CRMPHP
Dobrze
HTML5CSS3JavaScript
Początkujący
CMSVagrantAnsible