This website uses cookies

Our website, platform and/or any sub domains use cookies to understand how you use our services, and to improve both your experience and our marketing relevance.

CloudwaysCDN — a powerful solution that offers superior performance and satisfied global audience for your business. Read More

Let’s Build a Project Time Tracker with Symfony and VueJS

Updated on  14th June

22 Min Read
Reading Time: 22 minutes

As developers, we often love to keep track on the amount of time spent implementing a new feature, fixing bugs or generally carrying out a particular task during development. This has proven to be one of the ways to improve productivity.

Time-tracker-app is a project that has help boost my productivity and I thought the need to share the process of implementing it as well. With this mini app, you can add more than one project, specify the tasks you would love to carry out and eventually track how much time you have spent.

This project was built using one of my favorite PHP frameworks, Symfony, with its frontend powered fully by Vue.js, a progressive JavaScript framework.

Together, we will build this project and once completed, we should have :

To get the best out of this tutorial, a reasonable knowledge of PHP, JavaScript and Object Oriented Programming is advised.

This article will not cover or detailed the process of setting up Symfony and Vue.js. You can follow this article on Getting Started with Symfony and VueJS.

Getting Started

A composer can be used to quickly set up a new local Symfony project. Alternatively, you can easily set up a Cloudways account to launch a server and follow this well-written tutorial to install Symfony 4.

Open up a terminal and create a new Symfony project by running the command below:

This will create a skeleton project that is optimized for traditional web applications with the required dependencies already downloaded into it. In addition, it has basic directories and files for getting started with a web project.

Running Application

If you are running locally, spin up the inbuilt local server by changing directory into the newly created project and run the server as shown below:

Open your browser and navigate to http://localhost:8000. By now, you should see a welcome page.

User Management

In order to ensure that each project created is tied to a unique user, setting up a user management process is inevitable. We will do this by creating the entity for a user and then implement registration and login process.

Configure and Create Database

To start, open up the .env file in the project’s root directory, you should see something similar to the following:

Update the values with the credentials for your MySQL database.

  • Change db_user to YOUR_DATABASE_USERNAME
  • Change db_password to YOUR_DATABASE_PASSWORD
  • db_name to YOUR_DATABASE_NAME
  • The database host by default is and with a database port of 3306. You can leave this values as it is.
  • Configuring this credentials would also enable you to run a single command php bin/console doctrine:database:create to create the database with the name db_name, this will be covered later in the tutorial.

Set up Controllers and Entity

Just as you would have it in any application with a lot of request and responses, we will set up a couple of controllers to handle actions and redirect or return the appropriate response required for this application to function properly. We already have the maker bundle generated earlier on, let us make use of it to automatically generate the controllers.

Default Controller

This controller handles the route to the landing page and renders the view (i.e `index.html.twig file).  Run the make controller command to generate this

Locate src/Controller/DefaultController.php and update the contents as shown here :

Registration Controller

As pointed out earlier, it is important for users to register before creating projects.

In ./src/Controller/RegistrationController.php paste the following.

The controller above basically handles the registration process and redirect users to the login page once completed. A closer look at the controller, you would notice the addition of a UserType class. This is used to validate user’s input and eventually for submitting the registration form.

We will leverage on Symfony’s standard of building a form by creating a separate form class. Locate the src folder and create a new folder called Form. Within that Form folder, create a new file named UserType.php. Fill this file with :



To authenticate and authorize a user before start creating projects. Let’s create a Security controller. Feel free to give it any name that you want.


Finally, replace the contents of your config/packages/security.yaml file with :

The configuration file above, amongst other things, helps to set up how to load users from the database, configure the firewall, setup the login and logout path, and finally added an access control.

Add this to config/routes.yaml file.

Project Controller

The next file will be the project controller

Now open ./src/controller/ProjectController.php and paste the following code:

Here, we fetched all the projects belonging to the current authenticated user. In the saveProjects method, we grabbed the content of the project posted from the frontend and saved into the database.

Project Entity

A Project object to represent each project that will be created

Open ./src/Entity/Project and update the content with :

Timer Controller

Similar to managing projects, we will set up the controller for a timer

Locate this file and paste the code below:

Firstly, we ensure that the timer created is for a particular project by passing the specific project’s ID into the controller. The next function fetches and returns the current active timers and lastly, a method to stop the actively running timer set up by the current user.

Timer Entity

Create a Timer object with :

and update the content as shown:

Timer Repository

For every entity generated, Symfony automatically creates a repository class and map it for you. This helps to isolate complex queries from the controller and creates a helper method that can easily be used in your project.

Open ./src/Repository/TimerRepository  and dump the code below:

This makes it very easy for us to call findRunningTimer  and get all the active timer for a particular project within the TimerController.

Create Database Table/Schema and Run Migration

Now that we are done setting up the required entity and controller. The next line of action is to create the database specified earlier and run migrations. We already have DoctrineMigrationsBundle installed already, lets leverage on that.

Run this command to create the database:

Note: don’t forget to add the database credentials in your .env file as stated earlier.

To finally add a table to the database run :

If there are no errors, you should see a success message in the terminal indicating that a new migration class.

Finally, update your database with the SQL generated:

Setting Up The Frontend

As pointed out here in this article Symfony is not an opinionated framework when it comes to making a choice of JavaScript framework or library that powers the client side logic. Vue.js is the choice for this tutorial but before we set it up, let’s have a quick look at the directories within templates. You should see something similar to this.

These directories were automatically generated for each of the controllers. Let’s update the contents of the templates files. Needless to say that we only need to focus on just four of all these directories and that includes Default, Home, registration and security.

Templates in our project share common elements and since Symfony supports template inheritance, we will need to update the base layout template first.

Open ./templates/base.html.twig  and replace the content with :

We set the title for our application and added both CSS and JavaScript asset. Noticed the body block? That’s where the body of other templates that will inherit this layout will be rendered

Next, open the Default directory and use the content below for the index.html.twig file.


This file houses the form for registering the details of users within our application. It can be found in here ./templates/registration/index.html.twig. Change the name of the file to register.html.twig. This is not mandatory we just need to be consistent considering that we already have this files in our controller already. Once you are done, update the content like so :


To include the form for logging in users open ./templates/security directory and change the name of the file to login.html.twig, then change the content

Finally, all users will be redirected to a homepage once registration is successful and can proceed to add projects and timers.

Within ./templates/home directory, update the template file with the name home.html.twig and this content:

This looks simple enough, noticed the <home></home> element? That is a Vue component called home. We will create this in a bit.

Test the Application

Start the server if not already running :

Pretty ugly right? Let’s change this

Install Vue and Its Dependencies

To manage assets, we already have Encore installed so we are guaranteed a proper asset management with minimal effort of configuration. Before proceeding, ensure that you have Node.js and Yarn package manager installed on your machine.

other packages include Moment and Axios

Once completed, within the project directory, open webpack.config.js and configure Vue-loader and set up the entry point for both JavaScript and Stylesheets. Open it and replace the contents with :


Webpack encore configuration expects two separate entry points. So, create two subdirectories: js and css within assets directory. Then proceed to create app.js in the js directory and app.scss in css directory. By now, we will have the following directory structure

Here, I have only imported Bootstrap and added minimal styles for the application.

In the above code snippet, I made jQuery and Axios globals be used anywhere in the application, I then proceeded to require bootstrap. Next, I imported Vue and Home component and then created an instance of Vue, pass an element where Vue will attach itself to and register the Home component so that it can be accessible.

Create Home Component

Earlier we used a custom directive within the ./templates/home/home.html.twig file. We call it the HomeComponent. Lets create this component. For this, create a new directory assets/js/components and a new component file named HomeComponent.vue within it.

Home Component

Components in Vue.js consists of three parts structurally. They are :

  • <template></template>
  • <script></script>
  • <style></style>

We won’t need to use the style part of this component, but first, let’s update the contents of the template :

A few notes:

In the code above, once a project is created,

  • We basically loop through each of the timers and renders it to the view.
  • Included few methods to check if projects have been created,
  • Show timer for the created project
  • And then calculate time spent.

These methods will be declared within the script section of the component.


In the same file, update the script section with :

This might look daunting, but let’s try to break it down.

Firstly, we imported moment in order to properly calculate the time difference and then proceeded to declare variables that will be used later on within the file.

We implemented one of the lifecycle hooks used in Vue.js called created.

Within it, we make a request to the backend using Axios to GET all the created projects and assign it to the project’s variable. Furthermore, we check for if the project is active and then start the timer.

In addition, we also have stopActiveTimer, createTaskTimer, and createNewProject methods. These methods basically carry out the functionality of making a request to the backend in order to start a timer for a new task, create a timer for a task and create a new project respectively.

Run the Application

We have already included the HomeComponent as a custom tag <home></home> within ./templates/home/home.html.twig.

Run the command below to compile both JavaScript and SCSS file.

Now restart the server if not already running with :

You should be greeted with a page like this

And once you are logged in :


This project has not only provided an opportunity to build a mini-application that helps to improve productivity but also offers us the opportunity to explore the awesome combination of Symfony and Vue.js.

Hopefully, the knowledge gained here can be used to enhance other project built with Symfony.

I hope you found this tutorial helpful and if you would like to get the code and improve on it by adding extra features, you can find it here on GitHub.

Lastly, If you encountered any issues while building this, kindly leave a comment below.

Author of the Post: This post is contributed by Olususi Oluyemi. He is a tech enthusiast, programming freak and a web development junkie who loves to embrace new technology. You can find him on yemiwebby.

Share your opinion in the comment section. COMMENT NOW

Olususi k Oluyemi

A tech enthusiast, programming freak and a web development junkie who loves to embrace new technology.

Create PHP websites without the worry of server management.

Deploy your PHP app on optimized PHP hosting servers.

Get Our Newsletter
Be the first to get the latest updates and tutorials.