Sytuacja kobiet w IT w 2024 roku
17.12.20205 min
Zdzisław Bronikowski

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>