Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
2
Help us understand the problem. What is going on with this article?
@sangi

Symfonyのお勉強3 ~データベース接続~

More than 3 years have passed since last update.

ページ作成が完了したので最後にデータベースと接続してみたい

様々な方法でデータベースに接続できるのだが、今回はPDOを使用して接続しようと考えた

データベース接続

try {
    $sql = new \PDO ('mysql:dbname=データベース名; host=サーバアドレス;port=ポート番号; charset=utf8', 'データベースのユーザ名', 'データベースのパスワード');
    echo '接続に成功しました。';
} catch (PDOException $e) {
    echo "接続エラー:{$e->getMessage()}";
}
$sql = null;

try/catch文で接続したらecho文で成功したと表示し、エラーを検知したらエラーメッセージを表示するようにした
データベースはmysqladminを使用し、ユーザ名とパスワードもmysqladminのログイン時に使用するものを使う
アドレスはコマンド上でサーバーを動かす際に表示されるアドレスを使用
ポート番号はxamppのmysqlのポート番号を使用

それを組み込んだ結果がこちら
image.png
正しく接続されたことが確認できた

リスト表示

次にデータベースに格納されているデータをリスト表示する

今回使用するテーブル
image.png

//1
$stmt = $sql->query("select * from テーブル名");
//2
$count = 0;
$array[] = "";
//3
foreach ($stmt as $row) {
    $array[$count] = 'Task: ' . $row['カラム1'] . '   Time: ' . $row['カラム2'];
    $count++;
}
$sql = null;

1.sql文

select文を変数に格納する

2.初期値

変数と配列に初期値を設定する
配列arrayは複数データを格納するために使用
変数countは配列に格納する際、どこに格納するかを指定するために使用

3.データ取得

データベースからデータを複数取得するためforeach文を使い、データの数だけ繰り返し配列に格納する

image.png

実際にテーブルと全く同じデータを取得し表示できたことが確認できた

データの追加

次にデータをデータベースに追加する

ここで問題

テキストフィールドやボタンを作成し、そこから取得しようとしたのだが
GUIではもちろんPHPでは作成できない
PHPのファイルでPHPのタグの外にコードを書けばできるかもしれないがそれではviewの意味がない
ではさきほどのtwigファイルに書けばいいのではないか...
技術不足か調べ方が悪いのか、それかもともと方法がないのかわからないが、できない!!

そのため今回はformを作成しその上からテキストフィールドやボタンを作成しようと考えた

formの設定

まずデータの保存を行うためにTaskクラスというものを作成しなければならない
まいける.png

またTask.phpに処理を定義する

Task.php
namespace AppBundle\Entity;

class Task
{
    protected $task;
    protected $dueDate;

    public function getTask()
    {
        return $this->task;
    }

    public function setTask($task)
    {
        $this->task = $task;
    }

    public function getDueDate()
    {
        return $this->dueDate;
    }

    public function setDueDate(\DateTime $dueDate = null)
    {
        $this->dueDate = $dueDate;
    }
}
TestController.php
//1
$task = new Task();
//2
$form = $this->createFormBuilder($task)
    ->setMethod('GET')
    ->add('task', TextType::class)
    ->add('dueDate', DateType::class)
    ->add('save', SubmitType::class, array('label' => 'Create Task'))
    ->getForm();

//3
$form->handleRequest($request);

//4
if ($form->isSubmitted() && $form->isValid()) {

}

 1.タスクの生成

新しいタスクを生成する
その際にテキストフィールドにセットしておきたい場合は
先ほどのタスクからTask.phpから呼び出すことで可能となる

$task->setTask('Write a blog post');
$task->setDueDate(new \DateTime('tomorrow'));

2.form作成

createFormBuilderを使用しformを作成する
setmethodではメソッドの属性を設定する(使用しなくてもできる場合がある)
addではフォームにテキストフィールドやボタンを追加する
TextTypeではテキストフィールド
DateTypeは時間をプルダウン形式で選択できる
SubmitTypeはボタンを追加する

3.Request

フォームが送信されたか認識するもの
これによりプロパティに書き込み検証を行う

4.処理

値がsubmitできた時にif文の中に入るためこの中にデータベースに追加する処理などを書く

表示

最後にControllerからフォームをViewに飛ばし、Viewで表示を行う

Test.php
return $this->render('default/new.html.twig', array(
    'form' => $form->createView(),
));

test.html.twig
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}

image.png

これでようやく...

フォームを作成できたのでようやくデータベースに追加する作業を行う

データベース追加

項目ごとに別々にsubmitしたので項目ごと取得し、先ほどのif文の中に追加処理を書き込んでいく

//5
$taskdata = $form->get('task')->getViewData();
$duedate = $form->get('dueDate')->getViewData();
$due = $duedate['year'].'-'.$duedate['month'].'-'.$duedate['day'];

if ($form->isSubmitted() && $form->isValid()) {
    //6
    $insert = $sql->prepare("insert into symfony.task(task, datetime) VALUES (:task,:due)");
    $insert->bindParam(':task',$taskdata);
    $insert->bindValue(':due',$due);
    $insert->execute();
}

5.データ取得

先ほどsubmitしたデータを項目ごとに取得する
duedateは取得した時、年月日をまとめて取得してくるため
データベースに格納できるような形に直す

6.データの追加

insert文を変数に格納し、execute()で実際にデータベースに追加する
bindParam、bindValueの詳しい説明はこちらで
PDOでINSERTする(PHPでMySQLにデータ挿入)

実際に実装してみた結果

image.png

image.png

GenusController.php
<?php
namespace AppBundle\Controller;

use AppBundle\Entity\Task;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\Extension\Core\Type\DateType;

/**
 *
 */
class GenusController extends Controller
{
    /**
     * @Route("/genus/")
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     */

    public function showAction(Request $request)
    {
        try {
            $sql = new \PDO ('mysql:dbname=symfony; host=127.0.0.1;port=3306; charset=utf8', 'root', '');
            echo '接続に成功しました。';
        } catch (PDOException $e) {
            echo "接続エラー:{$e->getMessage()}";
        }

        $task = new Task();

        $form = $this->createFormBuilder($task)
            //getとpostの違いで苦戦
            ->setMethod('GET')
            ->add('task', TextType::class)
            ->add('dueDate', DateType::class)
            ->add('save', SubmitType::class, array('label' => 'Create Task'))
            ->getForm();

        $form->handleRequest($request);

        $taskdata = $form->get('task')->getViewData();
        $duedate = $form->get('dueDate')->getViewData();
        $due = $duedate['year'].'-'.$duedate['month'].'-'.$duedate['day'];

        if ($form->isSubmitted() && $form->isValid()) {
            $insert = $sql->prepare("insert into symfony.task(task, datetime) VALUES (:task,:due)");
            $insert->bindParam(':task',$taskdata);
            $insert->bindValue(':due',$due);
            $insert->execute();
        }

        $stmt = $sql->query("select * from symfony.task");
        $count = 0;
        $array[] = "";
        foreach ($stmt as $row) {
            $array[$count] = 'Task: ' . $row['task'] . '   Time: ' . $row['datetime'];
            $count++;
        }

        $sql = null;

        return $this->render('genus/show.html.twig', [
            'arrays' => $array,
            'form' => $form->createView(),
            'task' => $taskdata,
            'duedate' => $due
        ]);
    }
}

?>
Task.php
<?php
namespace AppBundle\Entity;

class Task
{
    protected $task;
    protected $dueDate;

    public function getTask()
    {
        return $this->task;
    }

    public function setTask($task)
    {
        $this->task = $task;
    }

    public function getDueDate()
    {
        return $this->dueDate;
    }

    public function setDueDate(\DateTime $dueDate = null)
    {
        $this->dueDate = $dueDate;
    }
}

?>
show.html.twig
{% extends 'base.html.twig' %}

{% block title %}Symfonyフレームワーク{% endblock %}

{% block body %}
    <ul>
        {% for array in arrays %}
            <li>{{ array }}</li>
        {% endfor %}
    </ul>
{% endblock %}
{% block form %}
    {{ form_start(form) }}
    {{ form_widget(form) }}
    {{ form_end(form) }}
{% endblock %}
base.html.twig
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8"/>
    <title>{% block title %}Welcome!{% endblock %}</title>
    {% block stylesheets %}{% endblock %}
    <link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}"/>
</head>
<body>
{% block body %}{% endblock %}
{% block javascripts %}{% endblock %}
</body>
<form>
    {% block form %}{% endblock %}
</form>
</html>

無事実装することに成功した!!!

実装してみて

今回簡易的にフレームワークを使用したのだが、まず日本語の資料が少ない!
そのため読み取る力や検索力が必要だと感じた。
また書いてある通りに進めていっても上手くいかなかったり、英語が分からなかったり資料で言っているものが自分のプログラムに存在しなかったりと大変だった....
またフォームから値を取得する際にフォームに作成したメソッドがpopメソッドになっており上手く取得できない状態が続き、直すのに時間がかかりました。
他にもPDOではなくducrightというsymfony独自?のやり方があったのだが全く分からない!!
あまりに理解できないことが多いため少し使いづらさがあったのだが、色々処理をまとめられるため、コードを見るとここで何を行っているかわかりやすい。
phpの知識が少しでもあったから良かったが、phpの知識がない状態だと少しきついかもしれない。

2
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
2
Help us understand the problem. What is going on with this article?