Buscar
  • Bianca Freitas

CRUD Project with PHP, linux and Symfony

Atualizado: 9 de Nov de 2020

Part 1 (Read)

For this project I am working with:

  • Symfony (v. 4.18.4)

  • Linux Ubuntu (v. 20.04)

  • PHP (v. 7.4.3)

  • Atom IDE and Firefox browser

After you have Symfony, PHP, Linux installed: make sure you have the following components installed as well


  • Composer (Composer is a dependency manager for PHP)

  • Twig: (Twig is a modern template engine for PHP)

  • Doctrine: (doctrine is a set of PHP libraries to work with databases)

(To find more about how to install the components, go to: symfony.com)


How Symfony Works ?

  • Controllers: It basically call the entities and load the views;

  • Entities: Entity is the file that will communicate with the database;

  • Repository: Repositories are like queries, it comes by default with some common methods like find or findAll, which are nothing more than queries. However, sometimes you may need something more specific, like andWhere (specify some condition), setMaxResults(), orderBy(),etc. And it is where the getters and setters are set;

  • Views: Give the html/css to the user. Where all Twig (template) files are saved


1. Configuring the response from symfony:


Go to ..\config\routes.yaml and set as follow:


2. Controller / Template:

Install the maker package from command prompt: composer require maker



Create another Controller from command prompt: php bin/console make:controller <name of Controller file>



Go to your IDE, refresh it, and you will find the following files have been created:


  • CrudController.php file

  • index.html.twig template file;



The CrudController.php file created brings the @Route annotations, which you can set as your response path. So, for example, if I set it to /crud/just_testing_how_it_works and go to the browser, you can call it by: localhost:8080/crud/just_testing_how_it_works



Now, lets modify the Controller, so it will return some data in the browser:


<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;

class CrudController extends AbstractController
{
    /**
     * @Route("/crud/just_testing_how_it_works", name="crud")
     */
    public function index()
    {
      $users = ['John', 'George', 'Paul', 'Ringo']
        return $this->render('crud/index.html.twig', [
            'users' => $users
            'controller_name' => 'CrudController',
        ]);
    }
}

Then, go to your template file (...\templates\crud\index.html.twig) to call the users set in the Controller:

Note: Here I am using for to call the users set in Controller above;


{% extends 'base.html.twig' %}
{% block title %}Hello Crud Controller{% endblock %}
{% block body %}
    <ul>
      {% for user in users %}
        <li>
          {{user}}
        </li>
      {% endfor %}
    </ul>
{% endblock %}

Open a command prompt screen and initialize the localhost by following command: php -S localhost:8080 -t public


From the browser, you will see the following:


3. ENTITY/DATABASE:


Symfony doesn't provide a database package, so it's recommended to use Doctrine. Doctrine maps PHP classes, known as entities to your database;


To install Doctrine, run the following command:

  • composer require symfony/orm-pack

  • composer require --dev symfony/maker-bundle


To create an entity file is pretty easy:

  • Enter the following command from prompt, screen run the following: php bin/console make:entity

  • Followed by <class/file_name> and <properties>

Note: You don’t need to enter the ID because doctrine generate it automatically for you


When you finish, just press enter twice, then go to your IDE, and you will find the Entity file created: ../src/Entity/User.php

Note: The getters and setters are made automatically as well;


Create a MariaDB database

  • Go to command prompt and enter: sudo mysql

  • Then: CREATE DATABASE <db_name>;

Create a new MariaDB user: CREATE USER '<userName>'@localhost IDENTIFIED BY '<user_password>';


Grant privileges to the user by entering the following command line: GRANT ALL PRIVILEGES ON *.* TO '<user_name>'@localhost IDENTIFIED BY ‘<user_password>’

Then: FLUSH PRIVILEGES


Import data from Entity to database:


  • Access the DATABASE you want to create the table: use <db_name>

  • If you go to your project, you will find a file named .env in your Symfony directory.

Note:

  • The .env file lets you customize your individual working environment variables.

  • The table created is based on the entities that have been set above;


To define the DATABASE_URL env var, we can set it on this file. However, when you are working in a team, and more than one person is using the same database, it’s recommended to make a local copy. To do it, run the following command line: cp .env .env.local



Then go to the file you just copied from .env and setup the DATABASE:


Create Repositories files:

To make changes to your database, Doctrine uses migration sql:

  • From command prompt, enter: php bin/console doctrine:migrations:generate

  • Then, run the command: php bin/console make:migration

  • And confirm with: yes


If you go back to your project, you will find the new repository class/file have been created:

Now, you can migrate your data to the database by the following command:

php bin/console doctrine:migrations:migrate

Access your database, and you will find the user table as set in your entity file you’ve created above:

  • Access MariaDB: sudo mysql

  • Select your DB: use <db_name>;

  • Check the tables available: SHOW TABLES;

  • Check the columns from table: SHOW COLUMNS FROM <table_name>;

Lets add some data into user table: INSERT INTO user VALUES (

null,'Bianca', 'Freitas', '01, Hughe Street, London - UK', 40, 'The Beatles');

Now, lets update the Controller (...\src\Controller\CrudController.php) to call use the repository in order to get the data from database (user table)

<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use App\Repository\UserRepository;

class CrudController extends AbstractController
{
    /**
     * @Route("/crud/just_testing_how_it_works", name="crud")
     */
    public function index(UserRepository $userRepository)
    {
        //NOTE: "findAll" is build in doctrine function which give all data from
        //the repository that I am calling, in this case UserRepository
      $users = $userRepository->findAll();
        return $this->render('crud/index.html.twig', [
            'controller_name' => 'CrudController',
            'users' => $users
        ]);
    }
}

Then, update the template file (..\templates\crud\index.html.twig) in order to see the content from user table in the browser:


{% extends 'base.html.twig' %}
{% block body %}
<!DOCTYPE html>
<html>
<head>
<style>
#users {
  font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
  border-collapse: collapse;
  width: 100%;
}
#users td, #users th {
  border: 1px solid #ddd;
  padding: 8px;
}
#users tr:nth-child(even){background-color: #f2f2f2;}
#users tr:hover {background-color: #ddd;}
#users th {
  padding-top: 12px;
  padding-bottom: 12px;
  text-align: left;
  background-color: #4CAF50;
  color: white;
}
</style>
</head>
<body>
  <table id="users">
    {% for user in users %}
      <tr>
        <th>First Name</th>
        <th>Last Name</th>
        <th>Address</th>
        <th>Age</th>
        <th>Favorite Band</th>
      </tr>
      <tr>
       <td>{{user.FirstName}}</td>
       <td>{{user.LastName}}</td>
       <td>{{user.Address}}}</td>
       <td>{{user.Age}}</td>
       <td>{{user.FavoriteBand}}</td>
      {% endfor %}
  </tr>
</table>
</body>
</html>
{% endblock %}

Reload the page and you will find the data from database:



Part 2 (Create)


So, now that we are able to read all users, it’s time to work on the Create part of the project


To do it, go to you Controller: …\src\Controller\CrudController.php

Note:

  • For the @route I need to setup the route that will load the create page;

  • From the first if / return I am calling a new template which It's still yet to be created;

  • From the second return I am also calling another template that still need to be implemented;

  • The Controller is calling Services\Service and Exception\UserException, which will be build in the next steps;

<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
use App\Services\Service;
use App\Repository\UserRepository;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;

class CrudController extends AbstractController
{
    /**
     * @Route("/crud/", name="index")
     */
    public function index(UserRepository $userRepository)
    {
	      $users = $userRepository->findAll();
        	return $this->render('crud/index.html.twig', [
            		'users' => $users
        ]);
    }
    /**
     * @Route("/crud/create", name="create_user")
     */
    public function create(Request $request, Service $service)
    {
        if ($request->getMethod() == 'GET') {
            return $this->render('crud/create.html.twig', [
            ]);
        } elseif ($request->getMethod() == 'POST') {
            try {
                $first_name= $request->get('FirstName');
                $Last_name= $request->get('LastName');
                $address= $request->get('Address');
                $age= $request->get('Age');
                $favorite_band= $request->get('FavoriteBand');
                $service->create($first_name, $Last_name, $address, $age, $favorite_band);
                $message = 'User: "'. $first_name .' '. $Last_name .' "  added to database 	successfully!!!.';
            }
            catch (\Exception $e) {
                $message = 'Error: '. $e->getMessage();
            }
            return $this->render('crud/result.html.twig', [
                'message' => $message
            ]);
        }
    }
}

Next step, creating a Service file: ...\src\Services\UserService.php

<?php

namespace App\Services;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use App\Exception\UserException;
use Doctrine\ORM\EntityManagerInterface;
use App\Entity\User;

//Call the EntityManager functions and clean up the data before passing to template
class UserService
{
    public function __construct(EntityManagerInterface $em)
    {
        try {
            $this->em = $em;
        } catch (\Exception $e) {
            throw new UserException($e->getCode(), "Problem with Service: " . $e->getMessage(), $e->getCode());
        }
    }
    public function findAll()
    {
        try {
            $users = $this->em->getRepository(UserRepository::class)->findAll();
            return $users;
        }
        catch (\Exception $e) {
            throw new UserException($e->getCode(),"Problem with Service: " . $e->getMessage(), $e->getCode());
        }
    }

    public function create($first_name, $Last_name, $address, $age, $favorite_band )
    {
        try {
            $users = new User();
            $users->setFirstName($first_name);
            $users->setLastName($Last_name);
            $users->setAddress($address);
            $users->setAge($age);
            $users->setFavoriteBand($favorite_band);
            $this->em->persist($users);
            $this->em->flush();
        }
        catch (\Exception $e) {
            throw new UserException($e->getCode(),"Problem with User: " . $e->getMessage(), $e->getCode());
        }
    }


Next step, creating the Exception file: ...\src\Exception\UserException


<?php
namespace App\Exception;
use Throwable;
use App\Exception\AbstractGenericException;

class UserException extends AbstractGenericException
{
    protected $message = "UserException: ";
    //the rest is inherited
}

With the create logic part of the project done, the templates need to be created:

  • So, the first part is add a button to the index Template

  • Go to ..\templates\crud\index.html.twig and improve the layout and also add a new button, which will redirect the user to another page (create page) when clicked:


{% extends 'base.html.twig' %}

{% block content %}

<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<!------ Include the above in your HEAD tag ---------->

<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.4.0/css/font-awesome.min.css" rel='stylesheet' type='text/css'>

<div class="container">
    <div class="row">
    <p></p>
    <h1>Crud Project - User Table</h1>
      <div class="col-md-10 col-md-offset-1">
        <div class="panel panel-default panel-table">
         <div class="panel-heading">
          <div class="row">
           <div class="col col-xs-6">
            <h3 class="panel-title">Users</h3></div>
             <div class="col col-xs-6 text-right">
<a class="btn btn-sm btn-primary btn-create" href="http://localhost:8080/crud/create/" role="button">Add New</a>
            </div>
           </div>
          </div>
         <div class="panel-body">
        <table class="table table-striped table-bordered table-list">
         <thead>
           <tr>
            <th><em class="fa fa-cog"></em></th>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Address</th>
            <th>Age</th>
            <th>Favorite Band</th>
           </tr>
          </thead>
       <tbody>
  {% for user in users %}
   <tr>
    <td align="center">
     <a href="/crud/{{ user.id }}" class="btn btn-default"><em class="fa fa-pencil"></em></a>
     <a class="btn btn-danger"><em class="fa fa-trash"></em></a>
    </td>
     <td>{{ user.FirstName }}</td>
     <td>{{ user.LastName }}</td>
     <td>{{ user.Address }}</td>
     <td>{{ user.Age }}</td>
     <td>{{ user.FavoriteBand }}</td>														    </a>
{% endfor %}
</tr>
</tbody>
</table>
              </div>
              <div class="panel-footer">
                <div class="row">
                  <div class="col col-xs-4">Page 1 of 5
                  </div>
                  <div class="col col-xs-8">
                    <ul class="pagination hidden-xs pull-right">
                      <li><a href="#">1</a></li>
                      <li><a href="#">2</a></li>
                      <li><a href="#">3</a></li>
                      <li><a href="#">4</a></li>
                      <li><a href="#">5</a></li>
                    </ul>
                    <ul class="pagination visible-xs pull-right">
                        <li><a href="#">«</a></li>
                        <li><a href="#">»</a></li>
                    </ul>
                  </div>
                </div>
              </div>
            </div>

</div></div></div>

{% endblock %}

If you reload your page, you must see the following:


Now, lets create the create form template: ...\src\templates\crud\create.html.twig

Note: There are a lot of free form templates available on the web.


{% extends "base.html.twig" %}
{% block content %}
<html>
<head>
<style type="text/css" >

@import url(https://fonts.googleapis.com/css?family=Roboto:400,300,600,400italic);
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  -webkit-font-smoothing: antialiased;
  -moz-font-smoothing: antialiased;
  -o-font-smoothing: antialiased;
  font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
body {
  font-family: "Roboto", Helvetica, Arial, sans-serif;
  font-weight: 100;
  font-size: 12px;
  line-height: 30px;
  color: #777;
  background: #4CAF50;
}
.container {
  max-width: 400px;
  width: 100%;
  margin: 0 auto;
  position: relative;
}
#contact input[type="text"],
#contact input[type="email"],
#contact input[type="tel"],
#contact input[type="url"],
#contact textarea,
#contact button[type="submit"] {
  font: 400 12px/16px "Roboto", Helvetica, Arial, sans-serif;
}
#contact {
  background: #F9F9F9;
  padding: 25px;
  margin: 150px 0;
  box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24);
}
#contact h3 {
  display: block;
  font-size: 30px;
  font-weight: 300;
  margin-bottom: 10px;
}
#contact h4 {
  margin: 5px 0 15px;
  display: block;
  font-size: 13px;
  font-weight: 400;
}
fieldset {
  border: medium none !important;
  margin: 0 0 10px;
  min-width: 100%;
  padding: 0;
  width: 100%;
}
#contact input[type="text"],
#contact input[type="email"],
#contact input[type="tel"],
#contact input[type="url"],
#contact textarea {
  width: 100%;
  border: 1px solid #ccc;
  background: #FFF;
  margin: 0 0 5px;
  padding: 10px;
}
#contact input[type="text"]:hover,
#contact input[type="email"]:hover,
#contact input[type="tel"]:hover,
#contact input[type="url"]:hover,
#contact textarea:hover {
  -webkit-transition: border-color 0.3s ease-in-out;
  -moz-transition: border-color 0.3s ease-in-out;
  transition: border-color 0.3s ease-in-out;
  border: 1px solid #aaa;
}

#contact textarea {
  height: 100px;
  max-width: 100%;
  resize: none;
}

#contact button[type="submit"] {
  cursor: pointer;
  width: 100%;
  border: none;
  background: #4CAF50;
  color: #FFF;
  margin: 0 0 5px;
  padding: 10px;
  font-size: 15px;
}

#contact button[type="submit"]:hover {
  background: #43A047;
  -webkit-transition: background 0.3s ease-in-out;
  -moz-transition: background 0.3s ease-in-out;
  transition: background-color 0.3s ease-in-out;
}

#contact button[type="submit"]:active {
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.5);
}

.copyright {
  text-align: center;
}

#contact input:focus,
#contact textarea:focus {
  outline: 0;
  border: 1px solid #aaa;
}

::-webkit-input-placeholder {
  color: #888;
}

:-moz-placeholder {
  color: #888;
}

::-moz-placeholder {
  color: #888;
}

:-ms-input-placeholder {
  color: #888;
}
</style>
</head>
<body>
  <div class="container">
    <form id="contact" method="post">
      <h3>New User Form</h3>
      <h4>Fill out the form carefully</h4>
      <fieldset>
        <input for "user" name="FirstName" placeholder="First Name" type="text" tabindex="1" required autofocus >
      </fieldset>
      <fieldset>
        <input for "user" name="LastName" placeholder="Last Name" type="text" tabindex="2" required>
      </fieldset>
      <fieldset>
        <input for "user" name="Age" placeholder="Your Age (optional)" type="text" tabindex="3" required>
      </fieldset>
      <fieldset>
        <input for "user" name="FavoriteBand" placeholder="Your Favorite Band (optional)" type="text" tabindex="4" required>
      </fieldset>
      <fieldset>
        <textarea for "user" name="Address" placeholder="Type your Address here..." tabindex="5" required></textarea>
      </fieldset>
      <fieldset>
        <button for "user" name="submit" type="submit" id="contact-submit" data-submit="...Sending">Submit</button>
      </fieldset>
    </form>
  </div>
</body></html>

{% endblock %}

From the frontend you will have the following:


Now we need to set the Result Template page:

Create a new template file: ..\templates\crud\result.html.twig


{% extends "base.html.twig" %}
{% block content %}
<html>
<head>
<style type="text/css" >
@import url(https://fonts.googleapis.com/css?family=Roboto:400,300,600,400italic);
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  -webkit-font-smoothing: antialiased;
  -moz-font-smoothing: antialiased;
  -o-font-smoothing: antialiased;
  font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
body {
  font-family: "Roboto", Helvetica, Arial, sans-serif;
  font-weight: 100;
  font-size: 12px;
  line-height: 30px;
  color: #777;
  background: #4CAF50;
}
.container {
  max-width: 400px;
  width: 100%;
  margin: 0 auto;
  position: relative;
}
#contact button[type="submit"] {
  font: 400 12px/16px "Roboto", Helvetica, Arial, sans-serif;
}
#contact {
  background: #F9F9F9;
  padding: 25px;
  margin: 150px 0;
  box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24);
}
#contact h3 {
  display: block;
  font-size: 30px;
  font-weight: 300;
  margin-bottom: 10px;
}
#contact h4 {
  margin: 5px 0 15px;
  display: block;
  font-size: 13px;
  font-weight: 400;
}
fieldset {
  border: medium none !important;
  margin: 0 0 10px;
  min-width: 100%;
  padding: 0;
  width: 100%;
}
#contact input[type="text"],
#contact input[type="email"],
#contact input[type="tel"],
#contact input[type="url"],
#contact textarea {
  width: 100%;
  border: 1px solid #ccc;
  background: #FFF;
  margin: 0 0 5px;
  padding: 10px;
}
#contact input[type="text"]:hover,
#contact input[type="email"]:hover,
#contact input[type="tel"]:hover,
#contact input[type="url"]:hover,
#contact textarea:hover {
  -webkit-transition: border-color 0.3s ease-in-out;
  -moz-transition: border-color 0.3s ease-in-out;
  transition: border-color 0.3s ease-in-out;
  border: 1px solid #aaa;
}

#contact textarea {
  height: 100px;
  max-width: 100%;
  resize: none;
}
#contact button[type="submit"] {
  cursor: pointer;
  width: 100%;
  border: none;
  background: #4CAF50;
  color: #FFF;
  margin: 0 0 5px;
  padding: 10px;
  font-size: 15px;
}
#contact button[type="submit"]:hover {
  background: #43A047;
  -webkit-transition: background 0.3s ease-in-out;
  -moz-transition: background 0.3s ease-in-out;
  transition: background-color 0.3s ease-in-out;
}
#contact button[type="submit"]:active {
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.5);
}
.copyright {
  text-align: center;
}
#contact input:focus,
#contact textarea:focus {
  outline: 0;
  border: 1px solid #aaa;
}
::-webkit-input-placeholder {
  color: #888;
}
:-moz-placeholder {
  color: #888;
}
::-moz-placeholder {
  color: #888;
}
:-ms-input-placeholder {
  color: #888;
}
</style>
</head>
<body>
  <div class="container">
    <form id="contact" action="/crud/">
      <h3> {{ message }} </h3>
      <fieldset>
      </fieldset>
      <fieldset>
        <button name="submit" type="submit" id="contact-submit" data-submit="...Sending">Return</button>
      </fieldset>
    </form>
  </div>
</body></html>
{% endblock %}

And the following screen will be shown when a new user have been added:


Part 3 (Update)


Lets start updating the Controller: ..\src\Controller\CrudController.php


<?php
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
use App\Exception\UserException;
use App\Services\UserService;
use App\Repository\UserRepository;
use App\Entity\User;

use Doctrine\ORM\EntityManagerInterface;


class CrudController extends AbstractController
{
    /**
     * @Route("/crud/", name="index")
     */
    public function index(UserRepository $userRepository)
    {

      $users = $userRepository->findAll();
        return $this->render('crud/index.html.twig', [
            'users' => $users
        ]);
    }

    /**
     * @Route("/crud/create", name="create_user")
     */
    public function create(Request $request, User $user)
    {

        if ($request->getMethod() == 'GET') {
            return $this->render('crud/create.html.twig', [
            ]);
        } elseif ($request->getMethod() == 'POST') {
            try {
                $first_name= $request->get('FirstName');
                $Last_name= $request->get('LastName');
                $address= $request->get('Address');
                $age= $request->get('Age');
                $favorite_band= $request->get('FavoriteBand');
                $service->create($first_name, $Last_name, $address, $age, $favorite_band);
                $message = 'User: "'. $first_name .' '. $Last_name .' "  added to database successfully!!!.';
            }
            catch (\Exception $e) {
                $message = 'Error: '. $e->getMessage();
            }
            return $this->render('crud/result.html.twig', [
                'message' => $message
            ]);
        }
    }

    /**
         * @Route("/crud/{id}", name="user_id")
         */
        public function read($id, Request $request, UserService $user)
        {
            //update an existing user
            $user = $user->findOne($id);
            return $this->render('crud/update.html.twig', [
                'user' => $user
            ]);
        }

        /**
         * @Route("/crud/update/{id}", name="user_update")
         */
        public function update(Request $request, UserService $user)
        {
            //update an existing user
            try {
                $user_id = $request->get('id');
                $first_name = $request->get('FirstName');
                $last_name = $request->get('LastName');
                $age = $request->get('Age');
                $favorite_band = $request->get('FavoriteBand');
                $address = $request->get('Address');
                $user->update($user_id, $first_name, $last_name, $age, $favorite_band, $address);
                  $message = 'User: "'. $first_name .' '. $last_name .' "  updated successfully!!!.';
            }
            catch (\Exception $e) {
                $message = 'Error: '. $e->getMessage();
            }
            return $this->render('crud/result.html.twig', [
                'message' => $message
            ]);
        }
}

Next Step is update the Service file: ..\src\Services\UserService.php


<?php

namespace App\Services;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use App\Exception\UserException;
use Doctrine\ORM\EntityManagerInterface;
use App\Entity\User;

//Call the EntityManager functions and clean up the data before passing to template
class UserService
{
    public function __construct(EntityManagerInterface $em)
    {
        try {
            $this->em = $em;
        } catch (\Exception $e) {
            throw new UserException($e->getCode(), "Problem with Service: " . $e->getMessage(), $e->getCode());
        }
    }
    public function findAll()
    {
        try {
            $users = $this->em->getRepository(UserRepository::class)->findAll();
            return $users;
        }
        catch (\Exception $e) {
            throw new UserException($e->getCode(),"Problem with Service: " . $e->getMessage(), $e->getCode());
        }
    }

    public function create($first_name, $Last_name, $address, $age, $favorite_band )
    {
        try {
            $users = new User();
            $users->setFirstName($first_name);
            $users->setLastName($Last_name);
            $users->setAddress($address);
            $users->setAge($age);
            $users->setFavoriteBand($favorite_band);
            $this->em->persist($users);
            $this->em->flush();
        }
        catch (\Exception $e) {
            throw new UserException($e->getCode(),"Problem with User: " . $e->getMessage(), $e->getCode());
        }
    }

    public function findOne($id)
    {
      try {
          $users = $this->em->getRepository(User::class)->find($id);
          return $users;
        }
        catch (\Exception $e) {
          throw new UserException($e->getCode(),"Problem with User: " . $e->getMessage(), $e->getCode());
        }
    }

    public function update($id, $first_name, $last_name, $age, $favorite_band, $address)
    {
      try {
          $users = $this->em->getRepository(User::class)->find($id);
          $users->setFirstName($first_name);
          $users->setLastName($last_name);
          $users->setAge($age);
          $users->setFavoriteBand($favorite_band);
          $users->setAddress($address);
          $this->em->persist($users);
          $this->em->flush();
        }
        catch (\Exception $e) {
          throw new UserException($e->getCode(),"Problem with User: " . $e->getMessage(), $e->getCode());
        }
    }
}

Create a new Update Template file: ..\templates\crud\update.html.twig


{% extends "base.html.twig" %}

{% block content %}
<html>
<head>
<style type="text/css" >

@import url(https://fonts.googleapis.com/css?family=Roboto:400,300,600,400italic);
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  -webkit-font-smoothing: antialiased;
  -moz-font-smoothing: antialiased;
  -o-font-smoothing: antialiased;
  font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
body {
  font-family: "Roboto", Helvetica, Arial, sans-serif;
  font-weight: 100;
  font-size: 12px;
  line-height: 30px;
  color: #777;
  background: #4CAF50;
}
.container {
  max-width: 400px;
  width: 100%;
  margin: 0 auto;
  position: relative;
}
#contact input[type="text"],
#contact input[type="text"],
#contact input[type="text"],
#contact input[type="text"],
#contact textarea,
#contact button[type="submit"] {
  font: 400 12px/16px "Roboto", Helvetica, Arial, sans-serif;
}
#contact {
  background: #F9F9F9;
  padding: 25px;
  margin: 150px 0;
  box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24);
}
#contact h3 {
  display: block;
  font-size: 30px;
  font-weight: 300;
  margin-bottom: 10px;
}
#contact h4 {
  margin: 5px 0 15px;
  display: block;
  font-size: 13px;
  font-weight: 400;
}
fieldset {
  border: medium none !important;
  margin: 0 0 10px;
  min-width: 100%;
  padding: 0;
  width: 100%;
}
#contact input[type="text"],
#contact input[type="text"],
#contact input[type="text"],
#contact input[type="text"],
#contact textarea {
  width: 100%;
  border: 1px solid #ccc;
  background: #FFF;
  margin: 0 0 5px;
  padding: 10px;
}
#contact input[type="text"]:hover,
#contact input[type="text"]:hover,
#contact input[type="text"]:hover,
#contact input[type="text"]:hover,
#contact textarea:hover {
  -webkit-transition: border-color 0.3s ease-in-out;
  -moz-transition: border-color 0.3s ease-in-out;
  transition: border-color 0.3s ease-in-out;
  border: 1px solid #aaa;
}
#contact textarea {
  height: 100px;
  max-width: 100%;
  resize: none;
}
#contact button[type="submit"] {
  cursor: pointer;
  width: 100%;
  border: none;
  background: #4CAF50;
  color: #FFF;
  margin: 0 0 5px;
  padding: 10px;
  font-size: 15px;
}
#contact button[type="submit"]:hover {
  background: #43A047;
  -webkit-transition: background 0.3s ease-in-out;
  -moz-transition: background 0.3s ease-in-out;
  transition: background-color 0.3s ease-in-out;
}
#contact button[type="submit"]:active {
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.5);
}
.copyright {
  text-align: center;
}
#contact input:focus,
#contact textarea:focus {
  outline: 0;
  border: 1px solid #aaa;
}
::-webkit-input-placeholder {
  color: #888;
}
:-moz-placeholder {
  color: #888;
}
::-moz-placeholder {
  color: #888;
}
:-ms-input-placeholder {
  color: #888;
}
</style>
</head>
<body>
  <div class="container">
    <form id="contact" action="/crud/update/{{ user.id }}" method="POST">
      <h3>Update - User Form</h3>
      <h4>Fill out the form carefully</h4>
      <fieldset>
        <input type="hidden" id="id" name="id" value="{{ user.id }}">
        <input for "user" id="FirstName" name="FirstName" value="{{user.FirstName}}" type="text" tabindex="1" required autofocus >
      </fieldset>
      <fieldset>
        <input for "user" id="LastName" name="LastName" value="{{user.LastName}}" type="text" tabindex="2" required>
      </fieldset>
      <fieldset>
        <input for "user" id="Age" name="Age" value="{{user.Age}}" type="text" tabindex="3" required>
      </fieldset>
      <fieldset>
        <input for "user" id="FavoriteBand" name="FavoriteBand" value="{{user.FavoriteBand}}" type="text" tabindex="4" required>
      </fieldset>
      <fieldset>
        <input for "user" id="Address" name="Address" value="{{user.Address}}" type="text" tabindex="5" required>
      </fieldset>
      <fieldset>
        <button name="submit" type="submit" id="contact-submit" data-submit="...Sending">Update</button>
      </fieldset>
    </form>
  </div>
</body></html>

{% endblock %}

Now, when you Edit icon clicked, the user will be redirected to the Update page:




Part 4 (Delete)


Go to ..src\Controller\CrudController.php and create the delete method(function):




<?php
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
use App\Exception\UserException;
use App\Services\UserService;
use App\Repository\UserRepository;
use App\Entity\User;

use Doctrine\ORM\EntityManagerInterface;


class CrudController extends AbstractController
{
    /**
     * @Route("/crud/", name="index")
     */
    public function index(UserRepository $userRepository)
    {

      $users = $userRepository->findAll();
        return $this->render('crud/index.html.twig', [
            'users' => $users
        ]);
    }

    /**
     * @Route("/crud/create", name="create_user")
     */
    public function create(Request $request, User $user)
    {

        if ($request->getMethod() == 'GET') {
            return $this->render('crud/create.html.twig', [
            ]);
        } elseif ($request->getMethod() == 'POST') {
            try {
                $first_name= $request->get('FirstName');
                $Last_name= $request->get('LastName');
                $address= $request->get('Address');
                $age= $request->get('Age');
                $favorite_band= $request->get('FavoriteBand');
                $service->create($first_name, $Last_name, $address, $age, $favorite_band);
                $message = 'User: "'. $first_name .' '. $Last_name .' "  added to database successfully!!!.';
            }
            catch (\Exception $e) {
                $message = 'Error: '. $e->getMessage();
            }
            return $this->render('crud/result.html.twig', [
                'message' => $message
            ]);
        }
    }

    /**
         * @Route("/crud/{id}", name="user_id")
         */
        public function read($id, Request $request, UserService $user)
        {
            //update an existing user
            $user = $user->findOne($id);
            return $this->render('crud/update.html.twig', [
                'user' => $user
            ]);
        }

        /**
         * @Route("/crud/update/{id}", name="user_update")
         */
        public function update(Request $request, UserService $user)
        {
            //update an existing user
            try {
                $user_id = $request->get('id');
                $first_name = $request->get('FirstName');
                $last_name = $request->get('LastName');
                $age = $request->get('Age');
                $favorite_band = $request->get('FavoriteBand');
                $address = $request->get('Address');
                $user->update($user_id, $first_name, $last_name, $age, $favorite_band, $address);
                $message = 'User: "'. $first_name .' '. $last_name .' "  updated successfully!!!.';
            }
            catch (\Exception $e) {
                $message = 'Error: '. $e->getMessage();
            }
            return $this->render('crud/result.html.twig', [
                'message' => $message
            ]);
        }

          /**
         * @Route("/crud/delete/{id}", name="user_delete")
         */
        public function delete(Request $request, UserService $user)
        {
            //update an existing User
            try {
                $user_id = $request->get('id');
                $users = $user->findOne($user_id);
                $first_name = $users->getFirstName();
                $last_name = $users->getLastName();
                $age = $users->getAge();
                $favorite_band = $users->getFavoriteBand();
                $address = $users->getAddress();
                $user->delete($user_id);
                $message = 'User: "'. $first_name .' '. $last_name .' "  deleted from database.';
            }
            catch (\Exception $e) {
                $message = 'Error: '. $e->getMessage();
            }
            return $this->render('crud/result.html.twig', [
                'message' => $message
            ]);
        }
}

From Service ..\src\Services\ServiceService.php set the delete function




<?php

namespace App\Services;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use App\Exception\UserException;
use Doctrine\ORM\EntityManagerInterface;
use App\Entity\User;

//Call the EntityManager functions and clean up the data before passing to template
class UserService
{
    public function __construct(EntityManagerInterface $em)
    {
        try {
            $this->em = $em;
        } catch (\Exception $e) {
            throw new UserException($e->getCode(), "Problem with Service: " . $e->getMessage(), $e->getCode());
        }
    }
    public function findAll()
    {
        try {
            $users = $this->em->getRepository(UserRepository::class)->findAll();
            return $users;
        }
        catch (\Exception $e) {
            throw new UserException($e->getCode(),"Problem with Service: " . $e->getMessage(), $e->getCode());
        }
    }

    public function create($first_name, $Last_name, $address, $age, $favorite_band )
    {
        try {
            $users = new User();
            $users->setFirstName($first_name);
            $users->setLastName($Last_name);
            $users->setAddress($address);
            $users->setAge($age);
            $users->setFavoriteBand($favorite_band);
            $this->em->persist($users);
            $this->em->flush();
        }
        catch (\Exception $e) {
            throw new UserException($e->getCode(),"Problem with User: " . $e->getMessage(), $e->getCode());
        }
    }

    public function findOne($id)
    {
      try {
          $users = $this->em->getRepository(User::class)->find($id);
          return $users;
        }
        catch (\Exception $e) {
          throw new UserException($e->getCode(),"Problem with User: " . $e->getMessage(), $e->getCode());
        }
    }

    public function update($id, $first_name, $last_name, $age, $favorite_band, $address)
    {
      try {
          $users = $this->em->getRepository(User::class)->find($id);
          $users->setFirstName($first_name);
          $users->setLastName($last_name);
          $users->setAge($age);
          $users->setFavoriteBand($favorite_band);
          $users->setAddress($address);
          $this->em->persist($users);
          $this->em->flush();
        }
        catch (\Exception $e) {
          throw new UserException($e->getCode(),"Problem with User: " . $e->getMessage(), $e->getCode());
        }
    }

    public function delete($id)
    {
      try {
          $user = $this->em->getRepository(User::class)->find($id);
          $this->em->remove($user);
          $this->em->flush();
        }
        catch (\Exception $e) {
          throw new UserException($e->getCode(),"Problem with User: " . $e->getMessage(), $e->getCode());
        }
    }
}

The last step is update the Index Template: ..\templates\crud\index.html.twig



{% extends 'base.html.twig' %}

{% block content %}

<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>

<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.4.0/css/font-awesome.min.css" rel='stylesheet' type='text/css'>

<div class="container">
    <div class="row">

    <p></p>
    <h1>Crud Project - User Table</h1>
     <div class="col-md-10 col-md-offset-1">
      <div class="panel panel-default panel-table">
       <div class="panel-heading">
        <div class="row">
          <div class="col col-xs-6">
          <h3 class="panel-title">Users</h3>
        </div>
        <div class="col col-xs-6 text-right">
<a class="btn btn-sm btn-primary btn-create" href="http://localhost:8080/crud/create/" role="button">Add New</a>
  </div>
 </div>
</div>
  <div class="panel-body">
   <table class="table table-striped table-bordered table-list">
    <thead>
     <tr>
      <th><em class="fa fa-cog"></em></th>
      <th>First Name</th>
      <th>Last Name</th>
      <th>Address</th>
      <th>Age</th>
      <th>Favorite Band</th>
     </tr>
    </thead>
 <tbody>
    {% for user in users %}
     <tr>
      <td align="center">
       <a href="/crud/{{ user.id }}" class="btn btn-default"><em class="fa fa-pencil"></em></a>
       <a href="/crud/delete/{{user.id}}" class="btn btn-danger"><em class="fa fa-trash"></em></a>
      </td>
        <td>{{ user.FirstName }}</td>
        <td>{{ user.LastName }}</td>
        <td>{{ user.Address }}</td>
        <td>{{ user.Age }}</td>
        <td>{{ user.FavoriteBand }}</td>													    
        </a>													 {% endfor %}
   </tr>
  </tbody>
</table>
</div>
  <div class="panel-footer">
   <div class="row">
    <div class="col col-xs-4">Page 1 of 5 </div>
      <div class="col col-xs-8">
       <ul class="pagination hidden-xs pull-right">
          <li><a href="#">1</a></li>
          <li><a href="#">2</a></li>
          <li><a href="#">3</a></li>
          <li><a href="#">4</a></li>
          <li><a href="#">5</a></li>
       </ul>
       <ul class="pagination visible-xs pull-right">
         <li><a href="#">«</a></li>
         <li><a href="#">»</a></li>
       </ul>
     </div>
    </div>
   </div>
  </div>
</div></div></div>

{% endblock %}






#CrudRead #Symfony #PHP #Twig #MariaDB

0 visualização0 comentário