Symfony 4 Blog

Ref: http://tutorials.mustangx.org/tutorials/create-advanced-blog-symfony-4-p1-2/

Getting Started with Symfony 4.x
There has been a lot of changes made for Symfony 4, seems to be ok though. I was quite confused, mainly the file structure of Symfony 3 is what I was used to. Then I discovered a nice and quick tutorial with the title Beginners Symfony 4 Tutorial.

The file structure has change if you are developing a web application. There are many, many changes that I may not catch as we move through this.

Step 1 – Symfony Website Skeleton
I am not going to detail this part, if you need that go to the link above.

Step 2 – Change into your new directory:

Step 3 – Install the Symfony Web Server Bundle: (NO NEED)

Step 4 – Now let’s fire up the web server

OR CAN USE PHP SERVER CLI : php bin/console server:run

That command will start the server and this one will stop it.

Note: You do not need to have any other server running. It may cause problems.

Create an .htaccess file (FOR APACHE WEBSERVER)
Mein is like this. Test it out and see if it works for you.

Now COPY & PASTE the following:

Setup the DB (MySql)
Inside the .env file (probably hidden) find this line

replace ‘db_user’, ‘db_password’ and ‘db_name’ according to  your database credential.
SORRY, ONLY ADMIN CAN SHOW THIS!
Once that’s done, we need to do this (make sure you have the correct db info added first):

If you already have the database, it’d show this error:

Auto Versioning setup
Get the auto versioning setup first.
NOTE: This has changed and is easier to install thanks to Flex.

The version is automatically updated with Composer and available in your application.

Console commands
There are two available console commands. The app:version:bump command is automatically called by Composer on every install and update.

Go ahead and test those two commands and see what it outputs.

Create an Advanced Blog with Symfony 4 – part3 (FrontController)
Last Updated On March 28, 2018
Introduction
This part of the tutorial will concentrate on getting a basic Homepage/Frontpage structure setup. I opted for a typical blog look.
We will remove files and folders as well add new ones. The Controller for the homepage will be created and the basic page should be viewable at the end.

Get Twitter Bootstrap Layout
I want to have a different look this time, so we will be using some premade templates from the Startbootstrap website. The one we want is released with an MIT license.

First create the PageController
It is easy to do with Symfony 4.

Let’s see what got created for us. We have a PageController.php file in our src/Controllers folder and inside of the templates folder we have a new folder and a new file, page/index.html.twig

Now that was all I discovered. Run the server: php bin/console s:r
then open the page on http://localhost:8000/page

Create Laravel Store with Vue

Ref: https://blog.pusher.com/ecommerce-laravel-vue-part-1/

In this article, we will cover how you can use Laravel to build a simple e-commerce application. After this tutorial, you should know how to use Laravel and Vue to make a web application and understand the basics of making an online store.

With the advent of the internet, many regular things became faster and easier. One of the things that improved is commerce. Commercial activities carried out on the web are known as e-commerce.

E-commerce applications make sales of goods and services over the internet possible. If you use the internet often, chances are you have come across one or even used one at some point.

Introduction
As we mentioned earlier, an e-commerce application makes selling goods and services online very convenient. It provides a listing of the products the seller wishes to sell showing their prices, then a page where you can see all the details of the single product selected, and finally, where to pay for the product and set how you wish to receive it.

With this in mind, we know that to have a useful e-commerce application, we’d need to develop the following:

A listing page to view all our products.
A single page to view product information.
A checkout page where the buyer can enter a delivery address and pay.
A simple dashboard for a buyer to see all purchased products, and know if they have shipped.
A way for the seller to add products to sell.
A way for the seller to see which orders users placed.
A way for the seller to show a product has been shipped to the user.
A way for the seller to see and update all product information.
Planning the structure of the application
From our breakdown above, you may see that this application will have two user types:

Administrator – The owner of the store.
Buyer – The person who wants to buy a gift for a friend.
You definitely know that the application will also have products that need to be stored. These products will be ordered and you need a way to store and track those orders. These would form the basis of any e-commerce platform.

The basic details we need to store in the different parts:

The basic operations we need the app to carry out, and where these are handled, are:

If you want to go a little deeper, you can consider adding categories, tags, warehouse items, more user types and many other things. However, we will not be considering them for this guide, but you should definitely try it on your own.

A good way to learn is by practicing. You can exercise your mind by doing the task in the previous paragraph.
Creating the application
We are going to use the Laravel CLI to make a new Laravel application. To create a new Laravel application, run the following command:

Then you can cd into the project we just created. The Laravel related commands we run throughout the article needs to be run from the root of the Laravel project.

Creating the models for the application
Models in Laravel provide a very convenient way to interact with the database. They provide methods for all the basic operations you need to run for your database table.

Let’s make the models that will interact with our database and hold business logic. New Laravel installations come with the User model out of the box, which can be found in app directory so let’s make the other two models:

We have added the -mr flag to the make:model command so that it will generate the accompanying migration and controller for the model.

Next open the app/User.php file and replace the contents with the following:

We are using SoftDeletes to allow us to mark a database record as deleted without actually deleting it completely. This is useful if you want to be able to restore the data.

We also have an array – $fillable, with the column names we want to mass assign on the users table. Mass assignment happens when we call our User model statically and pass an array to its create method.

Open app/Product.php file and edit as follows:

The Product model is quite similar to the User model. It has the $fillable array and also an orders method for establishing a relationship with orders placed on the application.

Now, open app/Order.php file and edit as follows:

The Order model looks slightly different from the other two but is essentially the same thing. We just established a different kind of relationship – belongsTo that shows which user made an order or which product was ordered.

Defining the migrations for the application
Migrations are a good way to create and maintain your application’s database. It essentially defines how tables should be created or modified.

Migrations are useful because they help you manage the database tables, columns and keys. You can share migration files instead of raw SQL, and because migration files are run chronologically, they make it easy to work with git, so it’s great for teams.

Open the create_users_table migrations file in the database/migrations directory and replace the content with the following:

Laravel is quite readable and you can probably figure out what is going on by reading the code. We defined which columns should exist in the table and their attributes.

There are many methods in the Blueprint class for migrations. You can read more here.

Next, open the create_products_table migrations file in the database/migrations directory and replace the code with the following:

Finally, open the create_orders_table migrations file in the database/migrations directory and replace the contents with the following:

Creating seeders for the application
Seeders are an excellent way to pre-populate our database with dummy data. We are going to use the seeder class to create the user account for our administration.

Create a seeder class by running the command below:

Now, open the file UserTableSeeder.php at the database/seeds directory and replace the content with the following:

The seeder class above will create a new admin user in the database.

Recall that when we defined the User model, we did not include is_admin in the fillable column. The reason is that we do not want anyone who tries to spoof our application to create an administrator user. This is why we had to create a user instance here so we can access all the columns from the user table.
Make another seeder class for our products table:

Open the database/seeds/ProductTableSeeder.php file and replace the contents with the following:

The data we populated the database with is from here and is for sample educational purposes. You may require permissions to actually use the images.
When you are done making the seeder, you need to edit the database/seeds/DatabaseSeeder.php, which actually invokes the seeders:

Now, when we execute the command to seed our database the DatabaseSeeder class is called and it calls the run which in turn class the seeder classes we had setup to run.

You can learn more about seeders here.
Creating the database for our application
We have defined everything we need our database to have. Now, we need to actually define the database itself. We are going to use SQLite for this guide, but you can any database you like. You should use a non-file based database like MySQL if in a production environment (NOTE: I’m going to use mysql instead).

If you want to use sqlite, Create a database file at database/database.sqlite (NOTE: I’m going to use mysql instead). Next, open your .env file and replace the following lines:

with

That is all for our database setup. Run the migrations to create the database tables for our application and seed it:

Defining and securing our endpoints
Our application uses Laravel and Vue to create the best application experience. This means we would need to define APIs to provide our Vue components with data.

Laravel, by default, has support for web and API routes. Web routes handle routing for dynamically generated pages accessed from a web browser, while API routes handle requests from clients that need a response in mostly JSON or XML format.

Our application will have APIs for most requests. We need to secure our APIs to ensure only authorised users will access it. For this, we will use Laravel Passport.

Install passport
To install passport, run the following command:

Laravel Passport comes with it’s own migrations, run the migrations using the following command:

Next, run the passport installation command to create the necessary keys for securing your application:

The above command will create encryption keys needed to generate secure access tokens plus “personal access” and “password grant” clients, which will be used to generate access tokens.

After the installation, you need to use the Laravel Passport HasApiToken trait in the User model. This trait will provide a few helper methods to your model, which allow you to inspect the authenticated user’s token and scopes.

Open the app/User.php file and edit as follows:

Next, call the Passport::routes method within the boot method of your AuthServiceProvider. This method will register the routes necessary to issue the tokens your app will need:

In the app/Providers/AuthServiceProvider.php file update as follows:

Finally, in your config/auth.php configuration file, you should set the driver option of the api authentication guard to passport.

That’s all for Laravel Passport.

Conclusion
So far, we have set up our application by defining all the models we need. We have also added migrations for our database, and lastly, we added Laravel Passport for handling authorization for our APIs.

The next thing we will look at is implementing the controllers to handle the different kinds of request we are going to make to the application and the views to interact with the application. Continue to part two.

In the previous chapter, we set up our application’s migrations and models, and installed Laravel Passport for authentication. We also planned what the application will look like. In this chapter, we will implement the controllers and handle all requests to our application.

Prerequisites
To continue with this part, please go through the first part of the series first and make sure you have all the requirements from that part.

Building our controllers
In the first chapter, we already defined our models and their accompanying controllers. These controllers reside in the app/Http/Controllers directory. The User model, however, does not have an accompanying controller, so we are going to create that first. Run the following command:

Now, open the created controller file app/Http/Controllers/UserController.php and replace the contents with the following:

Above we defined some class methods:

index() – returns all users with their orders.
login() – authenticates a user and generates an access token for that user. The createToken method is one of the methods Laravel Passport adds to our user model.
register() – creates a user account, authenticates it and generates an access token for it.
show() – gets the details of a user and returns them.
showOrders() – gets all the orders of a user and returns them.
We used Laravel’s Route-Model Binding to automatically inject our model instance into the controller. The only caveat is that the variable name used for the binding has to be the same as the one defined in the route as well.

Next, open the app/Http/Controllers/ProductController.php file and replace the contents with the following:

In the ProductController above we defined seven methods:

index() – fetches and returns all the product records.
store() – creates a product record.
show() – fetches and returns a single product.
uploadFile() – uploads the image for a product we created and returns the url for the product.
update() – updates the product record.
updateUnits() – adds new units to a product.
delete() – deletes a product.
Next, open the app/Http/Controllers/OrderController.php file and replace the content with the following:

In the OrderController above we have six methods:

index() – fetches and returns all the orders.
deliverOrder() – marks an order as delivered.
store() – creates an order.
show() – fetches and returns a single order.
update() – updates the order.
destroy() – deletes an order.
That’s it for our controllers. We have created the controller according to the specifications we laid out in the first part. Next thing we need to do is define our API routes.

Defining our application’s routes
Now that we have fully defined all the requests we would like to make to our application, let’s expose the APIs for making these requests. Open routes/api.php file and replace the content with the following:

Putting our route definitions in the routes/api.php file will tell Laravel they are API routes so Laravel will prefix the routes with a /api in the URL to differentiate them from web-routes.

Adding the auth:api middleware ensures any calls to the routes in that group must be authenticated.

A thing to note is, using the resource method on the Route class helps us create some additional routes under the hood without us having to create them manually. Read about resource controllers and routes here.

To see the full route list, run the following command: $ php artisan route:list

Since we will build the front end of this application in Vue, we need to define the web routes for it. Open the routes/web.php file and replace the contents with the following:

This will route every web request to a single entry point, which will be the entry for your Vue application.

Setting up Vue for the frontend
Vue is a progressive framework for building user interfaces. Unlike other monolithic frameworks, Vue is designed from the ground up to be incrementally adoptable – vuejs.org
Laravel comes with Vue bundled out of the box, so all we need to do to get Vue is to install the node packages. Run the following command:

Next, we will need VueRouter to handle the routing between the different components of our Vue application. To install VueRouter run the command below:

Next, let’s make the landing view file, which would mount our Vue application. Create the file resources/views/landing.blade.php and add the following code:

In the code above, we have the HTML for our application. If you look closely, you can see the app tag. This will be the entry point to our Vue application and where the components will be loaded.

Since we will use app.js to set up our VueRouter, we still need to have Bootstrap and Axios compiled. The import for Bootstrap and Axios is in the bootstrap.js file so we need to compile that.

Edit the webpack.mix.js file so it compiles all assets:

the webpack.mix.js file holds the configuration files for laravel-mix, which provides a wrapper around Webpack. It lets us take advantage of Webpack’s amazing asset compilation abilities without having to write Webpack configurations by ourselves. You can learn more about Webpack here.
Set up the homepage for the Vue application. Create a new file, resources/js/components/Home.vue, and add the following code to the file:

The code above within the opening and closing template tag we have the HTML of our Vue component. In there we loop through the contents of products and for each product we display the image, name, id, price and units available. We use the v-html attribute to render raw HTML, which makes it easy for us to use special characters in the product name.

In the script tag, we defined the data(), which holds all the variables we can use in our template. We also defined the mounted() method, which is called after our component is loaded. In this mounted method, we load our products from the API then set the products variable so that our template would be updated with API data.

In the same file, append the code below to the bottom:

In the code above, we have defined the style to use with the welcome component.

According to the Vue documentation: When a <style> tag has the scoped attribute, its CSS will apply to elements of the current component only. This is similar to the style encapsulation found in the Shadow DOM. It comes with some caveats but doesn’t require any polyfills.
Next create another file, resources/js/components/App.vue. This will be the application container where all other components will be loaded. In this file, add the following code:

In the Vue template above we used some Vue specific tags like router-link, which helps us generate links for routing to pages defined in our router. We also have the router-view, which is where all the child component pages will be loaded.

Next, below the closing template tag, add the following code:

In the script definition we have the methods property and in there we have three methods defined:

setDefaults() – sets the name of the user when the user is logged in as well as the type of user logged in.
change()– checks the current login status anytime it is called and calls the setDefaults method.
logout() – logs the user out of the application and routes the user to the homepage.
In our router-view component, we listen for an event loggedIn which calls the change method. This event is fired by our component anytime we log in. It is a way of telling the App component to update itself when a user logs in.

Next create the following files in the resources/js/components directory:

Admin.vue
Checkout.vue
Confirmation.vue
Login.vue
Register.vue
SingleProduct.vue
UserBoard.vue
These files would hold all the pages myStore would have. They need to be created prior to setting up VueRouter, so that it won’t throw an error.

To set up the routing for our Vue single page app, open your resources/js/app.js file and replace the contents with the following code:

Above, we have imported the VueRouter and we added it to our Vue application. We defined routes for our application and then registered it to the Vue instance so it is available to all Vue components.

Each of the route objects has a name, which we will use to identify and invoke that route. It also has a path, which you can visit directly in your browser. Lastly, it has a component, which is mounted when you visit the route.

On some routes, we defined meta, which contains variables we would like to check when we access the route. In our case, we are checking if the route requires authentication and if it is restricted to administrators or regular users only.

We set up the beforeEach middleware on the router that checks each route before going to it. The method takes these variables:

to – the route you want to move to.
from – the current route you are moving away from.
next – the method that finally moves to a defined route. When called without a route passed, it continues the navigation. If given a route, it goes to that route.
We use beforeEach to check the routes that require authentication before you can access them. For those routes, we check if the user is authenticated. If the user isn’t, we send them to the login page. If the user is authenticated, we check if the route is restricted to admin users or regular users. We redirect each user to the right place based on which access level they have.

Now add the following lines to the end of the app.js file

This instantiates the Vue application. In this global instance, we mount the App component only because the VueRouter needs it to switch between all the other components.

Now, we are ready to start making the other views for our application.

Conclusion
In this part, we implemented the controller logic that handles all the requests to our application and defined all the routes the application will use. We also set up Vue and VueRouter to prepare our application for building the core frontend.

In the next chapter of this guide, we are going to build the core frontend of the application and consume the APIs. See you in the next part.

Making the authentication pages
In the previous part, we created all the view files for our Vue application, although we did not add content to all of them. Let’s start with the login and register pages.

Open the resources/js/components/Login.vue file and paste in the following code:

Above we have a login form. We don’t have much functionality yet so let’s append the following code to the same file to add some Vue scripting:

Above we have a handleSubmit method that is fired when the form is submitted. In this method we attempt to authenticate using the API. If the authentication is successful, we save the access token and user data in localStorage so we can access them across our app.

We also emit a loggedIn event so the parent component can update as well. Lastly, we check if the user was sent to the login page from another page, then send the user to that page. If the user came to login directly, we check the user type and redirect the user appropriately.

Next, open the resources/js/components/Register.vue file and paste in the following:

Above we have the HTML for the registration form. Let’s add the script for the component below the closing template tag:

NOTE: I added a check for the password and the confirmation characters length. It should be more than 5 characters.
The register component operates similarly to the login component. We send the user data to the API for authentication and if we get a favourable response we save the token and user to localStorage.

Making the marketplace pages
We had already defined the homepage in the last chapter and returned a list of available products. Now, we are going to make all the other store pages.

Open the resources/js/components/SingleProduct.vue file and paste in the following code:

NOTE: USE backtick (`) INSTEAD OF apostroph (‘) ON let url VARIABLE TO PARSE ${this.$route.params.id}
Above we have the product as a data attribute, which we use to display information on the page like we did in the Home.vue file.

In the components script we defined Vue’s beforeMount method and fetched the product information there. beforeMount is called before the component is rendered, so it fetches the necessary data for rendering the component. If we get the data after the component has mounted, we would have errors before the component updates.

Next, open the resources/js/components/Checkout.vue file and paste the following code for the HTML template and style:

Above we defined the beforeMount method where we fetch product information. Then we have the mounted method where we check authentication status. In the methods property, we defined the checkUnits method that checks how many units the user wants to order, and then we define the placeOrder method that places the order.

Next, open the resources/js/components/Confirmation.vue file and paste the following code:

This component displays a simple thank you message and provides a link for the users to navigate to their dashboard to see the orders they have placed and the status of these orders. Let’s create the user dashboard next.

Creating the user dashboard
The user dashboard is where the users can see all their orders. Open the resources/js/components/UserBoard.vue file and paste in the following code for the template and style:

In the code above, we fetch all the user’s orders before the component is mounted, then loop through them and display them on the page.

Creating the admin dashboard
The admin dashboard is where new products are added, existing products modified and orders are set as delivered.

For the admin board, we will use four different components, which we will mount based on the url a user is accessing. Let’s see that in action. Open the resources/js/components/Admin.vue file and paste in the following:

In the code above, we import and register four components, which we have not yet created. They’ll be used as components inside Admin.vue parent component.

In our template, we defined the navigation for switching between the components. Each navigation link calls the setComponent method and then passes a value to it. The setComponent method just sets the component using a switch statement.

Let’s create the first component for the Admin component. Create the Main.vue file in resources/js/components/admin directory and paste the following into the file:

In the code above we are calling the APIs for users, orders and products, and returning their data.

Create the Orders.vue file in resources/js/components/admin and paste the following into the file:

In beforeMount we fetch all the orders placed before the component is rendered.

When the Deliver button is clicked, the deliver method is fired. We call the API for delivering orders. To get the change to reflect on the page instantly, we call [$forceUpdate](https://vuejs.org/v2/api/#vm-forceUpdate).

Create the Users.vue file in resources/js/components/admin and paste in the following code:

Above we fetch all the user data and then display it on the page.

Next, create the Products.vue file in resources/js/components/admin and paste the following template code:

In the methods property we defined the following methods:

newProduct() – called when we want to initiate a new local product object.
endEditing() – called when we are done editing a product.
addProduct() – called when we are want to add a new product.
We imported a ProductModal component, which we will create next. The modal will be used to edit an existing or create a new product. Double clicking on a product listed fires up the modal for editing the product.

Create the ProductModal.vue file in resources/js/components/admin and paste in the following template and style code:

When the modal receives a product’s data, it pre-fills each field with the data. When we attach an image and submit the modal’s form, it is uploaded and the url for the image is returned to us.

We update the image attribute of the product with the url, then emit a close event and return the product with it. If no image is attached, we emit a close event and return the product data along with it.

This modal component is an example provided in Vue documentation here

Payments
There are many payment options for e-commerce platforms. You choose depending on your needs and what is available in your country. Many popular payment processors like Stripe have excellent guides on integrating into a JavaScript or PHP application which you can use. This tutorial won’t cover that though, you can take it as an exercise for practise.

Building our application
We are done building our application. The next thing to do will be to compile our Vue application and serve our Laravel backend. Run the command to build the application.

Admin user:
email: admin@admin.com
name: Admin
password: secret

Create/Register a new user:
email: advcha@yahoo.com
name: Satria
password: satria

Create Laravel CMS

Ref: https://pusher.com/tutorials/cms-laravel-vue-part-1

Install Laravel Installer globally (It’d be better than ‘create project’ and download from the laravel source):

Create the Laravel CMS Project ‘laravel-cms’:

Go to the project directory and check the laravel version:

Run it for the first time:

Open it on your browser : http://localhost:8000/Set up the database (MySql)
Create a new database ‘laravel_cms’
then modify .env file to match your mysql server setting and database

SETTING UP USER ROLES
Like most content management systems, we are going to have a user role system so that our blog can have multiple types of users; the admin and regular user. The admin should be able to create a post and perform other CRUD operations on a post. The regular user, on the other hand, should be able to view and comment on a post.

For us to implement this functionality, we need to implement user authentication and add a simple role authorization system.

SETTING UP USER AUTHENTICATION
Laravel provides user authentication out of the box, which is great, and we can key into the feature by running a single command:

The above will create all that’s necessary for authentication in our application so we do not need to do anything extra.

SETTING UP ROLE AUTHORIZATION
We need a model for the user roles so let’s create one and an associated migration file:

In the database/migrations folder, find the newly created migration file and update the CreateRolesTable class (2019_01_21_031440_create_roles_table.php) with this snippet:
Update with adding two new fields: $table->string(‘name’) and
$table->string(‘description’):

We intend to create a many-to-many relationship between the User and Role models so let’s add a relationship method on both models.

Open the User model and add the following method:

Open the Role model and include the following method:

We are also going to need a pivot table to associate each user with a matching role so let’s create a new migration file for the role_user table:

In the database/migrations folder, find the newly created migration file and update the CreateRoleUserTable class with this snippet:

Next, let’s create seeders that will populate the users and roles tables with some data. In your terminal, run the following command to create the database seeders:

In the database/seeds folder, open the RoleTableSeeder.php file and replace the contents with the following code:

Open the UserTableSeeder.php file and replace the contents with the following code:

We also need to update the DatabaseSeeder class. Open the file and update the run method as seen below:

Next, let’s update the User model. We will be adding a checkRoles method that checks what role a user has. We will return a 404 page where a user doesn’t have the expected role for a page. Open the User model and add these methods:

Let’s modify the RegisterController.php file in the Controllers/Auth folder so that a default role, the user role, is always attached to a new user at registration.

Open the RegisterController and update the create action with the following code:

Now let’s migrate and seed the database so that we can log in with the sample accounts. To do this, run the following command in your terminal:

SOLUTION: check again ‘CreateRolesTable’ Class in /home/teddy/Documents/works/laravel/laravel-cms/database/migrations/2019_01_21_031440_create_roles_table.php. Somehow the ‘up’ function is changed!!!

SOLUTION: It’s related with the above problem!
This is working:

In order to test that our roles work as they should, we will make an update to the HomeController.php file. Open the HomeController and update the index method as seen below:

Now, only administrators should be able to see the dashboard. In a more complex application, we would use a middleware to do this instead.
We can test that this works by serving the application and logging (http://localhost:8000/login) in both user accounts: satriaf@yahoo.com (user) and advcha@yahoo.com (admin).

Remember that in our UserTableSeeder.php file, we defined satriaf@yahoo.com as a regular user and advcha@yahoo.com as an admin, so satriaf@yahoo.com should see a 404 error after logging in and advcha@yahoo.com should be able to see the homepage. Also http://localhost:8000/home would be redirected to http://localhost:8000/login if none logged in!

We will also confirm that whenever a new user registers, he is assigned a role and it is the role of a regular user. We will create a new user and call him user1@yahoo.com (password: user1_123) , he should see a 404 error right after:

It works just as we wanted it to, however, it doesn’t really make any sense for us to redirect a regular user to a 404 page. Instead, we will edit the HomeController so that it redirects users based on their roles, that is, it redirects a regular user to a regular homepage and an admin to an admin dashboard.

Open the HomeController.php file and update the index method as seen below:

After we login as an user, we missed the logout link here. So modify the main template welcome.blade.php to add the logout link:

But if we click the logout link, it’d show an error:

It means we need to add a route for ‘logout’. Add the route in web.php:

Ref: https://stackoverflow.com/questions/44716379/laravel-5-4-24-throws-methodnotallowedhttpexception-during-logout-of-users

If we serve our application and try to log in using the admin account, we will hit a 404 error because we do not have a controller or a view for the admin/dashboard route. Let’s create the AdminController with this command:

We will add the /admin/ route to our routes/web.php file:

Note that we wrote /admin/{any} here because we intend to serve every page of the admin dashboard using the Vue router. When we start building the admin dashboard in the next article, we will let Vue handle all the routes of the /admin pages.

Let’s update the AdminController.php file to use the auth middleware and include an index() action method:

In the index() action method, we included a snippet that will ensure that only admin users can visit the admin dashboard and perform CRUD operations on posts. If we try to login as an admin, it’d show this error:

Because we haven’t create any view for the admin route. We’ll create it with vue router later.

Here, we will create the Post model and start building the frontend for the application.

Our application allows different levels of accessibility for two kinds of users; the regular user and admin. Now, we will focus on building the view that the regular users are permitted to see.

Before we build any views, let’s create the Post model as it is imperative to rendering the view. We will create the Post model with an associated resource controller and a migration file using this command:

We added the r flag because we want the controller to be a resource controller. The m flag will generate a migration for the model.

Let’s navigate into the database/migrations folder and update the CreatePostsTable class that was generated for us:

We included a user_id property because we want to create a relationship between the User and Post models. A Post also has an image field, which is where its associated image’s address will be stored.

CREATING A DATABASE SEEDER FOR THE POST TABLE
We will create a new seeder file for the posts table using this command:

Let’s navigate into the database/seeds folder and update the PostTableSeeder.php file:

Let’s open the DatabaseSeeder and update it with the following code:

When we run this seeder, it will create two new posts and assign both of them to the admin user whose ID is 2. We are attaching both posts to the admin user because the regular users are only allowed to view posts and make comments; they can’t create a post. We will use this command to migrate our tables and seed the database:

DEFINING THE RELATIONSHIPS
Just as we previously created a many-to-many relationship between the User and Role models, we need to create a different kind of relationship between the Post and User models.

We will define the relationship as a one-to-many relationship because a user will have many posts but a post will only ever belong to one user.

Open the User model and include the method below:

Open the Post model and include the method below:

SETTING UP THE ROUTES
At this point in our application, we do not have a front page with all the posts listed. Let’s create so anyone can see all of the created posts. Asides from the front page, we also need a single post page in case a user needs to read a specific post.

Let’s include two new routes to our routes/web.php file:

The first route will match requests to the root of our application and will be handled by the PostController@all action:

In the routes/web.php file, there will already be a route definition for the / address, you will have to replace it with the new route definition above.
The second route will handle requests for specific Post items and will be handled by the PostController@single action:

With these two new routes added, here’s what the routes/web.php file should look like this:

SETTING UP THE POST CONTROLLER
In this section, we want to define the handler action methods that we registered in the routes/web.php file so that our application know how to render the matching views.

First, let’s add the all() method:

Here, we want to retrieve five created posts per page and send to the landing view. We will create this view shortly.

Next, let’s add the single() method to the controller:

In the method above, we used a feature of Laravel named route model binding to map the URL parameter to a Post instance with the same ID. We are returning a single view, which we will create shortly. This will be the view for the single post page.

BUILDING OUR VIEWS
Laravel uses a templating engine called Blade for its frontend. We will use Blade to build these parts of the frontend before switching to Vue in the next chapter.

Navigate to the resources/views folder and create two new Blade files. They are landing.blade.php and single.blade.php

These are the files that will load the views for the landing page and single post page. Before we start writing any code in these files, we want to create a simple layout template that our page views can use as a base.

In the resources/views/layouts folder, create a Blade template file and call it master.blade.php. This is where we will define the inheritable template for our single and landing pages.

Open the master.blade.php file and update it with this code:

Now we can inherit this template in the landing.blade.php file, open it and update it with this code:

Let’s do the same with the single.blade.php file, open it and update it with this code:

TESTING THE APPLICATION
We can test the application to see that things work as we expect. When we serve the application, we expect to see a landing page and a single post page. We also expect to see two posts because that’s the number of posts we seeded into the database.

We will serve the application using this command:

We have used simple placeholder images here because we haven’t built the admin dashboard that allows CRUD operations to be performed on posts.

In the coming chapters, we will add the ability for an admin to include a custom image when creating a new post.

CONCLUSION
In this chapter, we created the Post model and defined a relationship on it to the User model. We also built the landing page and single page.

We will start building the admin frontend of the CMS. This is the first part of the series where we will integrate Vue and explore Vue’s magical abilities.

Laravel ships with Vue out of the box so we do not need to use the Vue-CLI or reference Vue from a CDN.  Please see package.json file on the project root.

This makes it possible for us to have all of our application, the frontend, and backend, in a single codebase.

Every newly created instance of a Laravel installation has some Vue files included by default, we can see these files when we navigate into the resources/js/components folder.

SETTING UP VUE AND VUEROUTER
Before we can start using Vue in our application, we need to first install some dependencies using NPM. To install the dependencies that come by default with Laravel, run the command below:

We will be managing all of the routes for the admin dashboard using vue-router so let’s pull it in:

When the installation is complete, the next thing we want to do is open the resources/js/app.js file and replace its contents with the code below:

In the snippet above, we imported the VueRouter and added it to the Vue application. We also imported a Homepage and a Read component. These are the components where we will write our markup so let’s create both files.

NOTE: IF YOU EDIT THE JS/VUE TEMPLATE, DON’T FORGET TO STOP ‘php artisan serve’ THEN RUN ‘npm run dev’ THEN START AGAIN ‘php artisan serve’. IF NOT, YOU’D NOT SEE THE CHANGES YOU MADE!!!

Open the resources/js/components folder and create four files:
Homepage.vue – this will be the parent component for the admin dashboard frontend.
Read.vue – this will be component that displays all the available posts on the admin dashboard.
Create.vue – this will be the component where an admin user can create a new post.
Update.vue – this will be the component that displays the view where an admin user can update an existing post.
Note that we didn’t create a component file for the delete operation, this is because it is going to be possible to delete a post from the Read component. There is no need for a view.
In the resources/js/app.js file, we defined a routes array and in it, we registered a read route. During render time, this route’s path will be mapped to the Read component.

In the previous article, we specified that admin users should be shown an admin.dashboard view in the index method, however, we didn’t create this view. Let’s create the view. Open the resources/views folder and create a new folder called admin. Within the new resources/views/admin folder, create a new file and called dashboard.blade.php. This is going to be the entry point to the admin dashboard, further from this route, we will let the Vue Router handle everything else.

Open the resources/views/admin/dashboard.blade.php file and paste in the following code:

Our goal here is to integrate Vue into the application, so we included the resources/js/app.js file with this line of code:

For our app to work, we need a root element to bind our Vue instance unto. Before the <script> tag, add this snippet of code:

We earlier defined the Homepage component as the wrapping component, that’s why we pulled it in here as the root component. For some of the frontend components to work correctly, we require some details of the logged in admin user to perform CRUD operations. This is why we passed down the userName (:user-name) and userId (:user-id) props to the Homepage component.

We need to prevent the CSRF error from occurring in our Vue frontend, so include this snippet of code just before the <title> tag:

This snippet will ensure that the correct token is always included in our frontend, Laravel provides the CSRFprotection for us out of the box.

SETTING UP THE HOMEPAGE VIEW
Open the Homepage.vue file that we created some time ago and include this markup template:

We added a router-link in this template, which routes to the Create component.

We are passing the userId data to the create component because a userId is required during Post creation.

UPDATED: I want to pass more variables (like user-email and user-admin. DON’T USE SINGLE WORD VARIABLE LIKE title. USE DASH SEPARATED VARIABLE) to vue template. So modify resources/views/admin/dashboard.blade.php:

Then catch the variables in resources/js/components/Homepage.vue:

Here is the passing variables in Vue chrome toolbarsHow to get user role name on the vue template???
I need to create a helper function in User model (app/User.php):

Ref: https://stackoverflow.com/questions/36719279/laravel-5-2-how-to-get-the-role-of-current-user-when-using-zizaco-entrust
Then modify again resources/views/admin/dashboard.blade.php to get the user role with auth()->user()->getRole():

Then catch the props value in resources/js/components/Homepage.vue:

 

Let’s include some styles so that the page looks good. Below the closing template tag, paste the following code:

We are using the scoped attribute on the <style> tag because we want the CSS to only be applied on the Homepage component.
Next, let’s add the <script> section that will use the props we passed down from the parent component. We will also define the method that controls the log out feature here. Below the closing style tag, paste the following code:

SETTING UP THE READ VIEW
In the resources/js/app.js file, we defined the path of the read component as /admin/dashboard, which is the same address as the Homepage component. This will make sure the Read component always loads by default.

In the Read component, we want to load all of the available posts. We are also going to add Update and Delete options to each post. Clicking on these options will lead to the update and delete views respectively.

Open the Read.vue file and paste the following:

Above, we have the template to handle the posts that are loaded from the API (Will get the data via API later). Next, paste the following below the closing template tag:

In the script above, we defined a getPosts() method that requests a list of posts from the backend server. We also defined a posts object as a data property. This object will be populated whenever posts are received from the backend server.

We defined next and prev data string properties to store pagination links and only display the pagination options where it is available.

Lastly, we defined a deletePost() method that takes the id of a post as a parameter and sends a DELETE request to the API interface using Axios.

TESTING THE APPLICATION
Now that we have completed the first few components, we can serve the application using this command:

We will also build the assets so that our JavaScript is compiled for us. To do this, will run the command below in the root of the project folder:

We can visit the application’s URL http://localhost:8000 and log in as an admin user. It’d show the admin dashboard but no post will show up because we haven’t set up the ‘api’ route yet.
NOTE: If you got an error like

It because the app.js file not loaded. Probably you call it wrong. Make sure app.js in this path:

NOT in laravel-cms/resources/assets/js/app.js

We will start building the API for the application. We will create an API for CRUD operations that an admin will perform on posts and we will test the endpoints using Postman.

BUILDING THE API USING LARAVEL’S API RESOURCES
The Laravel framework makes it very easy to build APIs. It has an API resources feature that we can easily adopt in our project. You can think of API resources as a transformation layer between Eloquent models and the JSON responses that will be sent back by our API.

ALLOWING MASS ASSIGNMENT ON SPECIFIED FIELDS
Since we are going to be performing CRUD operations on the posts in the application, we have to explicitly specify that it’s permitted for some fields to be mass-assigned data. For security reasons, Laravel prevents mass assignment of data to model fields by default.

Open the Post.php file and include this line of code:

DEFINING API ROUTES
We will use the apiResource() method to generate only API routes. Open the routes/api.php file and add the following code:

Because we will be handling the API requests on the /posts URL using the PostController, we will have to include some additional action methods in our post controller.

CREATING THE POST RESOURCE
At the beginning of this section, we already talked about what Laravel’s API resources are. Here, we create a resource class for our Post model. This will enable us to retrieve Post data and return formatted JSON format.

To create a resource class for our Post model run the following command in your terminal:

A new PostResource.php file will be available in the app/Http/Resources directory of our application. Open up the PostResource.php file and replace the toArray() method with the following:

The job of this toArray() method is to convert our Post resource into an array. As seen above, we have specified the fields on our Post model, which we want to be returned as JSON when we make a request for posts.

We are also explicitly casting the dates, created_at and update_at, to strings so that they would be returned as date strings. The dates are normally an instance of Carbon.

Now that we have created a resource class for our Post model, we can start building the API’s action methods in our PostController and return instances of the PostResource where we want.

ADDING THE ACTION METHODS TO THE POST CONTROLLER
The usual actions performed on a post include the following:
Create – the process of creating a new post.
Read – the process of reading one or more posts.
Update – the process of updating an already published post.
Delete – the process of deleting a post.
In the last article, we already implemented a kind of ‘Read’ functionality when we defined the all and single methods. These methods allow users to browse through posts on the homepage.

In this section, we will define the methods that will resolve our API requests for creating, reading, updating and deleting posts.

The first thing we want to do is import the PostResource class at the top of the PostController.php file:

Because we created the PostController as a resource controller, we already have the resource action methods included for us in the PostController.php file, we will be updating them with fitting snippets of code.

BUILDING THE HANDLER ACTION FOR THE CREATE OPERATION
In the PostController update the store() action method with the code snippet below. It will allow us to validate and create a new post:

Here’s a breakdown of what this method does:
Receives a new request.
Validates the request.
Creates a new post.
Returns the post as a PostResource, which in turn returns a JSON formatted response.

BUILDING THE HANDLER ACTION FOR THE READ OPERATIONS
What we want here is to be able to read all the created posts or a single post. This is possible because the apiResource() method defines the API routes using standard REST rules.

This means that a GET request to this address, http://localhost:8000/api/posts, should be resolved by the index() action method. Let’s update the index method with the following code:

This method will allow us to return a JSON formatted collection of all of the stored posts. We also want to paginate the response as this will allow us to create a better view on the admin dashboard.

Following the RESTful conventions as we discussed above, a GET request to this address, http://localhost:8000/api/posts/id, should be resolved by the show() action method. Let’s update the method with the fitting snippet:

Awesome, now this method will return a single instance of a post resource upon API query.

BUILDING THE HANDLER ACTION FOR THE UPDATE OPERATION
Next, let’s update the update() method in the PostController class. It will allow us to modify an existing post:

This method receives a request and a post id as parameters, then we use route model binding to resolve the id into an instance of a Post. First, we validate the $request attributes, then we update the title and body fields of the resolved post.

BUILDING THE HANDLER ACTION FOR THE DELETE OPERATION
Let’s update the destroy() method in the PostController class. This method will allow us to remove an existing post:

In this method, we resolve the Post instance, then delete it and return a 204 response code.

Our methods are complete. We have a method to handle our CRUD operations.We are not done with the dashboard just yet. In the next part, we will add the views that lets us create and update posts.

we have built the first parts of the admin dashboard using Vue. We also made it into an SPA with the VueRouter, this means that visiting the pages does not cause a reload to the web browser.

We only built the wrapper component and the Read component that retrieves the posts to be loaded so an admin can manage them.

we will build the view that will allow users to create and update posts. We will start writing code in the Update.vue and Create.vue files that we created in the previous article.

When we are done with this part, we will have additional functionalities like create and updating.

INCLUDING THE NEW ROUTES IN VUE ROUTER
In the previous article, we only defined the route for the Read component, we need to include the route configuration for the new components that we are about to build; Update and Create.

Open the resources/js/app.js file and replace the contents with the code below:

Above, we have added two new components to the JavaScript file. We have the Create and Read components. We also added them to the router so that they can be loaded using the specified URLs.

BUILDING THE CREATE VIEW
Open the Create.vue file and update it with this markup template:

Above we have the template for the Create component. If there is an error during post creation, there will be a field indicating the specific error. When a post is successfully published, there will also a message saying it was successful.

Let’s include the script logic that will perform the sending of posts to our backend server and read back the response.

After the closing template tag add this:

In the script above, we defined a create() method that takes the values of the input fields and uses the Axios library to send them to the API interface on the backend server. Within this method, we also update the status of the operation, so that an admin user can know when a post is created successfully or not.

BUILDING THE UPDATE VIEW
Let’s start building the Update component. Open the Update.vue file and update it with this markup template:

This template is similar to the one in the Create component. Let’s add the script for the component.

Below the closing template tag, paste the following:

In the script above, we make a call to the getPosts() method as soon as the component is mounted. The getPosts() method fetches the data of a single post from the backend server, using the postId.

When Axios sends back the data for the post, we update the input fields in this component so they can be updated.

Finally, the update() method takes the values of the fields in the components and attempts to send them to the backend server for an update. In a situation where the fails, we get instant feedback.

TESTING THE APPLICATION
To test that our changes work, we want to refresh the database and restore it back to a fresh state. To do this, run the following command in your terminal:

Next, let’s compile our JavaScript files and assets. This will make sure all the changes we made in the Vue component and the app.js file gets built. To recompile, run the command below in your terminal:

Lastly, we need to serve the application. To do this, run the following command in your terminal window:

If you had the serve command running before, then you might need to restart it.
We will visit the application’s http://localhost:8000 and log in as an admin user. From the dashboard, you can test the create and update feature

Now, we will be adding support for comments. We will also ensure that the comments on each post are updated in realtime, so a user doesn’t have to refresh the page to see new comments.

ADDING COMMENTS TO THE BACKEND
When we were creating the API, we did not add the support for comments to the post resource, so we will have to do so now. Open the API project in your text editor as we will be modifying the project a little.

The first thing we want to do is create a model, controller, and a migration for the comment resource. To do this, open your terminal and cd to the project directory and run the following command:

The command above will create a model called Comment, a controller called CommentController, and a migration file in the database/migrations directory.

UPDATING THE COMMENTS MIGRATION FILE
To update the comments migration navigate to the database/migrations folder and find the newly created migration file for the Comment model. Let’s update the up() method in the file:

We included user_id and post_id fields because we intend to create a link between the comments, users, and posts. The body field will contain the actual comment.

DEFINING THE RELATIONSHIPS AMONG THE COMMENT, USER, AND POST MODELS
In this application, a comment will belong to a user and a post because a user can make a comment on a specific post, so we need to define the relationship that ties everything up.

Open the User model and include this method:

This is a relationship that simply says that a user can have many comments. Now let’s define the same relationship on the Post model. Open the Post.php file and include this method:

Finally, we will include two methods in the Comment model to complete the second half of the relationships we defined in the User and Post models.

Open the app/Comment.php file and include these methods:

Since we want to be able to mass assign data to specific fields of a comment instance during comment creation, we will include this array of permitted assignments in the app/Comment.php file:

We can now run our database migration for our comments:

CONFIGURING LARAVEL TO BROADCAST EVENTS USING PUSHER
We already said that the comments will have a realtime functionality and we will be building this using Pusher, so we need to enable Laravel’s event broadcasting feature.

Open the config/app.php file and uncomment the following line in the providers array:

Next, we need to configure the broadcast driver in the .env file. Replace from BROADCAST_DRIVER=log TO

Let’s pull in the Pusher PHP SDK using composer:

CONFIGURING PUSHER
For us to use Pusher in this application, it is a prerequisite that you have a Pusher account. You can create a free Pusher account here then login to your dashboard and create an app.

Once you have created an app, we will use the app details to configure pusher in the .env file:

SORRY, ONLY ADMIN CAN SHOW THIS!

Update the Pusher keys with the app credentials provided for you under the Keys section on the Overview tab on the Pusher dashboard.

BROADCASTING AN EVENT FOR WHEN A NEW COMMENT IS SENT
To make the comment update realtime, we have to broadcast an event based on the comment creation activity. We will create a new event and call it CommentSent. It is to be fired when there is a successful creation of a new comment.

Run command in your terminal:

There will be a newly created file in the app\Events directory, open the CommentSent.php file and ensure that it implements the ShouldBroadcast interface.

Open and replace the file with the following code:

In the code above, we created two public properties, user and comment, to hold the data that will be passed to the channel we are broadcasting on. We also created a private channel called comment. We are using a private channel so that only authenticated clients can subscribe to the channel.
NOTE: Make sure ‘CommentSent’ class implements ‘ShouldBroadcast’ class. When I accidentally missing to implement it, the message can’t be broadcasted at real time properly. I need to refresh the page to see the incoming message on the another login.

DEFINING THE ROUTES FOR HANDLING OPERATIONS ON A COMMENT
We created a controller for the comment model earlier but we haven’t defined the web routes that will redirect requests to be handled by that controller.

Open the routes/web.php file and include the code below:

SETTING UP THE ACTION METHODS IN THE COMMENTCONTROLLER
We need to include two methods in the CommentController.php file, these methods will be responsible for storing and retrieving methods. In the store() method, we will also be broadcasting an event when a new comment is created.

Open the CommentController.php file and replace its contents with the code below:

In the store method above, we are validating then creating a new post comment. After the comment has been created, we broadcast the CommentSent event to other clients so they can update their comments list in realtime.

In the index method we just return the comments belonging to a post along with the user that made the comment.

ADDING A LAYER OF AUTHENTICATION
Let’s add a layer of authentication that ensures that only authenticated users can listen on the private comment channel we created.

Add the following code to the routes/channels.php file:

ADDING COMMENTS TO THE FRONTEND
In the second article of this series, we created the view for the single post landing page in the single.blade.php file, but we didn’t add the comments functionality. We are going to add it now. We will be using Vue to build the comments for this application so the first thing we will do is to include Vue in the frontend of our application.

Open the master layout template and include Vue to its <head> tag. Just before the <title> tag appears in the master.blade.php file, include this snippet:

The csrf_token() is there so that users cannot forge requests in our application. All our requests will pick the randomly generated csrf-token and use that to make requests.

Related: CSRF in Laravel: how VerifyCsrfToken works and how to prevent attacks

Now the next thing we want to do is update the resources/js/app.js file so that it includes a template for the comments view.

Open the file and replace its contents with the code below:

Above we imported the Comment component and then we added it to the list of components in the applications Vue instance.

Now create a Comments.vue file in the resources/js/components directory. This is where all the code for our comment view will go. We will populate this file later on.

INSTALLING PUSHER AND LARAVEL ECHO
For us to be able to use Pusher and subscribe to events on the frontend, we need to pull in both Pusher and Laravel Echo. We will do so by running this command:

Laravel Echo is a JavaScript library that makes it easy to subscribe to channels and listen for events broadcast by Laravel.
Now let’s configure Laravel Echo to work in our application. In the resources/js/bootstrap.js file, find and uncomment this snippet of code:

The key and cluster will pull the keys from your .env file so no need to enter them manually again.
Now let’s import the Comments component into the single.blade.php file and pass along the required the props.

Open the single.blade.php file and replace its contents with the code below:

BUILDING THE COMMENTS VIEW
Open the Comments.vue file and add the following markup template below:

Now, we’ll add a script that defines two methods:

fetchComments() – this will fetch all the existing comments when the component is created.
addComment() – this will add a new comment by hitting the backend server. It will also trigger a new event that will be broadcast so all clients receive them in realtime.
In the same file, add the following below the closing template tag:

In the created() method above, we first made a call to the fetchComments() method, then we created a listener to the private comment channel using Laravel Echo. Once this listener is triggered, the comments property is updated.

TESTING THE APPLICATION
Now let’s test the application to see if it is working as intended. Before running the application, we need to refresh our database so as to revert any changes. To do this, run the command below in your terminal:

Next, let’s build the application so that all the changes will be compiled and included as a part of the JavaScript file. To do this, run the following command on your terminal:

Finally, let’s serve the application using this command:

To test that our application works visit the application URL http://localhost:8000 on two separate browser windows, we will log in to our application on each of the windows as a different user.

We will finally make a comment on the same post on each of the browser windows and check that it updates in realtime on the other window:

IMPROVEMENTS:
Currently the comments can only be displayed if the user is logged in. But I want to display them also if no user is logged in but it only read the comments and can’t add the comment. So modify resources/views/single.blade.php:

Make user-name variable is empty string. Then modify resources/js/components/Comments.vue on the template and the script:

On the template, show the text input if ‘userName’ is exist. Otherwise just show the login link. Then on the script, get the broadcast only if the ‘userName’ is exist:

Anyway if the user not logged in, they can’t get the real time message!

How to show the message counter?
Modify the template and the script in resources/js/components/Comments.vue. On the script, add a new computed variable ‘commentCount’ in ‘data’. Why not in ‘props’? because the variables in ‘data’ can be changed real time. not only on the page load.

‘commentCount’ is calculated in ‘addComment’ method when the new comment is inserted. Also in ‘fetchComments’ when the page is loaded. To calculate it at real time, also put it in ‘created’. Then show the counter on the template:

So the message counter would appear on the post page (single page). But how to show the counter on the homepage?
So modify resources/views/landing.blade.php to show the counter:

give the bookmark link (#) to jump straight to the comments section. Modify resources/js/components/Comments.vue to add the bookmark ‘comments’:

 

My M2 Projects – Magento 2 Extensions & Themes

Magento 2 Extensions List:
/home/teddy/Documents/works/aliceisback/app/code/Advcha/CustomPage
/home/teddy/Documents/works/aliceisback/app/code/Advcha/EmptyZipCheckout
/home/teddy/Documents/works/aliceisback/app/code/Advcha/LeadtimeAttr
/home/teddy/Documents/works/aliceisback/app/code/Advcha/RecentlyViewed
/home/teddy/Documents/works/aliceisback/app/code/Advcha/ShipFrom
/home/teddy/Documents/works/aliceisback/app/code/Advcha/ShiptoNz
/home/teddy/Documents/works/aliceisback/app/code/Advcha/VendorAdminUrlkey
/home/teddy/Documents/works/aliceisback/app/code/Advcha/VendorCustomAttr
/home/teddy/Documents/works/aliceisback/app/code/Advcha/VendorDelivery
/home/teddy/Documents/works/aliceisback/app/code/Advcha/VendorInvoice
/home/teddy/Documents/works/aliceisback/app/code/Advcha/VendorProduct
/home/teddy/Documents/works/aliceisback/app/code/Advcha/VendorTierShipCustomAttr
/home/teddy/Documents/works/aliceisback/app/code/Advcha/CustomCategory.tar.gz
/home/teddy/Documents/works/aliceisback/app/code/Advcha/Leadtime.tar.gz
/home/teddy/Documents/works/aliceisback/app/code/Advcha/VendorAdminUrlkey.tar.bz2
/home/teddy/Documents/works/aliceisback/app/code/Advcha/VendorCustomAttr.1.0.0.tar.gz
/home/teddy/Documents/works/aliceisback/app/code/Afterpay/Afterpay
/home/teddy/Documents/works/aliceisback/app/code/Amasty/Base
/home/teddy/Documents/works/aliceisback/app/code/Amasty/Fpc
/home/teddy/Documents/works/aliceisback/app/code/Amasty/GiftCard
/home/teddy/Documents/works/aliceisback/app/code/Amasty/Sorting
/home/teddy/Documents/works/aliceisback/app/code/ClassyLlama/SortedProductsWidget
/home/teddy/Documents/works/aliceisback/app/code/DigitalPianism/Reindex
/home/teddy/Documents/works/aliceisback/app/code/Ebizmarts/MailChimp
/home/teddy/Documents/works/aliceisback/app/code/Emipro/Custompayment
/home/teddy/Documents/works/aliceisback/app/code/Iazel/RegenProductUrl
/home/teddy/Documents/works/aliceisback/app/code/Ibnab/CloudZoomy
/home/teddy/Documents/works/aliceisback/app/code/IWD/All
/home/teddy/Documents/works/aliceisback/app/code/IWD/Opc
/home/teddy/Documents/works/aliceisback/app/code/MagePal/GmailSmtpApp
/home/teddy/Documents/works/aliceisback/app/code/Mageplaza/SelectOptions
/home/teddy/Documents/works/aliceisback/app/code/Mageplaza/Simpleshipping
/home/teddy/Documents/works/aliceisback/app/code/Mageplaza/SimpleshippingChina
/home/teddy/Documents/works/aliceisback/app/code/Mageplaza/FileUploader.tar.gz
/home/teddy/Documents/works/aliceisback/app/code/Mageplaza/HelloWorld.tar.bz2
/home/teddy/Documents/works/aliceisback/app/code/Mageplaza/SelectData.tar.gz
/home/teddy/Documents/works/aliceisback/app/code/Mageplaza/SelectOptions.tar.gz
/home/teddy/Documents/works/aliceisback/app/code/MageWorx/AlsoBought
/home/teddy/Documents/works/aliceisback/app/code/MageWorx/AlsoBoughtMeta
/home/teddy/Documents/works/aliceisback/app/code/MyModule/MyAttribute
/home/teddy/Documents/works/aliceisback/app/code/Opalo/Kaizen
/home/teddy/Documents/works/aliceisback/app/code/PHPCuong/Region
/home/teddy/Documents/works/aliceisback/app/code/Rokanthemes/BestsellerProduct
/home/teddy/Documents/works/aliceisback/app/code/Rokanthemes/Blog
/home/teddy/Documents/works/aliceisback/app/code/Rokanthemes/Brand
/home/teddy/Documents/works/aliceisback/app/code/Rokanthemes/Categorytab
/home/teddy/Documents/works/aliceisback/app/code/Rokanthemes/CustomMenu
/home/teddy/Documents/works/aliceisback/app/code/Rokanthemes/Featuredpro
/home/teddy/Documents/works/aliceisback/app/code/Rokanthemes/LayeredAjax
/home/teddy/Documents/works/aliceisback/app/code/Rokanthemes/MostviewedProduct
/home/teddy/Documents/works/aliceisback/app/code/Rokanthemes/Newproduct
/home/teddy/Documents/works/aliceisback/app/code/Rokanthemes/Onsaleproduct
/home/teddy/Documents/works/aliceisback/app/code/Rokanthemes/OpCheckout
/home/teddy/Documents/works/aliceisback/app/code/Rokanthemes/PriceCountdown
/home/teddy/Documents/works/aliceisback/app/code/Rokanthemes/ProductTab
/home/teddy/Documents/works/aliceisback/app/code/Rokanthemes/QuickView
/home/teddy/Documents/works/aliceisback/app/code/Rokanthemes/RokanBase
/home/teddy/Documents/works/aliceisback/app/code/Rokanthemes/SearchbyCat
/home/teddy/Documents/works/aliceisback/app/code/Rokanthemes/SlideBanner
/home/teddy/Documents/works/aliceisback/app/code/Rokanthemes/Testimonial
/home/teddy/Documents/works/aliceisback/app/code/Rokanthemes/Themeoption
/home/teddy/Documents/works/aliceisback/app/code/Rokanthemes/VerticalMenu
/home/teddy/Documents/works/aliceisback/app/code/Shippit/Shipping
/home/teddy/Documents/works/aliceisback/app/code/TestVendor/TestPayment
/home/teddy/Documents/works/aliceisback/app/code/Trive/AdaptiveResize
/home/teddy/Documents/works/aliceisback/app/code/Unirgy/Dropship
/home/teddy/Documents/works/aliceisback/app/code/Unirgy/DropshipBatch
/home/teddy/Documents/works/aliceisback/app/code/Unirgy/DropshipMicrosite
/home/teddy/Documents/works/aliceisback/app/code/Unirgy/DropshipMicrositePro
/home/teddy/Documents/works/aliceisback/app/code/Unirgy/DropshipMulti
/home/teddy/Documents/works/aliceisback/app/code/Unirgy/DropshipSellYours
/home/teddy/Documents/works/aliceisback/app/code/Unirgy/DropshipShippingClass
/home/teddy/Documents/works/aliceisback/app/code/Unirgy/DropshipShippingClassLimit
/home/teddy/Documents/works/aliceisback/app/code/Unirgy/DropshipSplit
/home/teddy/Documents/works/aliceisback/app/code/Unirgy/DropshipTierCommission
/home/teddy/Documents/works/aliceisback/app/code/Unirgy/DropshipTierShipping
/home/teddy/Documents/works/aliceisback/app/code/Unirgy/DropshipVacation
/home/teddy/Documents/works/aliceisback/app/code/Unirgy/DropshipVendorAskQuestion
/home/teddy/Documents/works/aliceisback/app/code/Unirgy/DropshipVendorProduct
/home/teddy/Documents/works/aliceisback/app/code/Unirgy/DropshipVendorTax
/home/teddy/Documents/works/aliceisback/app/code/Unirgy/MarketplaceSuite
/home/teddy/Documents/works/aliceisback/app/code/Unirgy/Rma
/home/teddy/Documents/works/aliceisback/app/code/Unirgy/SimpleLicense
/home/teddy/Documents/works/aliceisback/app/code/Unirgy/SimpleUp
/home/teddy/Documents/works/aliceisback/app/code/Unirgy/Unirgy_DropshipShippingClassLimit.zip
/home/teddy/Documents/works/aliceisback/app/code/Webkul/Stripe
/home/teddy/Documents/works/aliceisback/app/code/Zgento/LightBox
/home/teddy/Documents/works/aliceisback/app/code/MagePsycho.tar.bz2
/home/teddy/Documents/works/aliceisback/app/design/frontend/bs_eren/bs_eren1 … bs_eren7
/home/teddy/Documents/works/aliceisback/app/design/frontend/Opalo/kaizen

/home/teddy/Documents/works/fontaineind/app/code/Advcha/Newsletter
/home/teddy/Documents/works/fontaineind/app/code/Advcha/ProductEnquiry
/home/teddy/Documents/works/fontaineind/app/code/Afterpay/Afterpay
/home/teddy/Documents/works/fontaineind/app/code/Aitoc/AbandonedCartAlertsPro
/home/teddy/Documents/works/fontaineind/app/code/Amasty/Base
/home/teddy/Documents/works/fontaineind/app/code/Amasty/ProductAttachment
/home/teddy/Documents/works/fontaineind/app/code/Biztech/Authentication
/home/teddy/Documents/works/fontaineind/app/code/Biztech/Authentication_bkp_10-05-18
/home/teddy/Documents/works/fontaineind/app/code/Biztech/Mobileassistant
/home/teddy/Documents/works/fontaineind/app/code/Biztech/Mobileassistant_bkp_10-05-18
/home/teddy/Documents/works/fontaineind/app/code/Codazon/AjaxCartPro
/home/teddy/Documents/works/fontaineind/app/code/Codazon/AjaxLayeredNav
/home/teddy/Documents/works/fontaineind/app/code/Codazon/MegaMenu
/home/teddy/Documents/works/fontaineind/app/code/Codazon/OneStepCheckout
/home/teddy/Documents/works/fontaineind/app/code/Codazon/ProductFilter
/home/teddy/Documents/works/fontaineind/app/code/Codazon/ProductLabel
/home/teddy/Documents/works/fontaineind/app/code/Codazon/QuickShop
/home/teddy/Documents/works/fontaineind/app/code/Codazon/Slideshow
/home/teddy/Documents/works/fontaineind/app/code/Codazon/ThemeOptions
/home/teddy/Documents/works/fontaineind/app/code/Dfe/Fontaine
/home/teddy/Documents/works/fontaineind/app/code/Ebizmarts/MailChimp
/home/teddy/Documents/works/fontaineind/app/code/Impinge/Bigpost
/home/teddy/Documents/works/fontaineind/app/code/Magefan/Blog
/home/teddy/Documents/works/fontaineind/app/code/Mageplaza/GoogleRecaptcha
/home/teddy/Documents/works/fontaineind/app/code/Mageplaza/LayeredNavigation
/home/teddy/Documents/works/fontaineind/app/code/Mageplaza/LayeredNavigationPro
/home/teddy/Documents/works/fontaineind/app/code/Mageplaza/Osc
/home/teddy/Documents/works/fontaineind/app/code/Mageplaza/SeoUrl
/home/teddy/Documents/works/fontaineind/app/code/Mageplaza/Smtp
/home/teddy/Documents/works/fontaineind/app/code/MageWorx/SearchSuiteAutocomplete
/home/teddy/Documents/works/fontaineind/app/code/MageWorx/SearchSuiteAutocompleteMeta
/home/teddy/Documents/works/fontaineind/app/code/Min/Base
/home/teddy/Documents/works/fontaineind/app/code/Min/Tags
/home/teddy/Documents/works/fontaineind/app/code/Mirasvit/CacheWarmer
/home/teddy/Documents/works/fontaineind/app/code/Mirasvit/Core
/home/teddy/Documents/works/fontaineind/app/code/Mirasvit/Report
/home/teddy/Documents/works/fontaineind/app/code/Mirasvit/ReportApi
/home/teddy/Documents/works/fontaineind/app/code/Mirasvit/Mirasvit.zip
/home/teddy/Documents/works/fontaineind/app/code/Mirasvit/Mirasvit_old.zip
/home/teddy/Documents/works/fontaineind/app/code/Ti/AdminTheme
/home/teddy/Documents/works/fontaineind/app/code/Ti/Catalog
/home/teddy/Documents/works/fontaineind/app/code/Ti/CheckoutSuccess
/home/teddy/Documents/works/fontaineind/app/code/Ti/ContactCon
/home/teddy/Documents/works/fontaineind/app/code/Ti/CoreBugOOSPriceFix
/home/teddy/Documents/works/fontaineind/app/code/Ti/Customer
/home/teddy/Documents/works/fontaineind/app/code/Ti/CustomToolbar
/home/teddy/Documents/works/fontaineind/app/code/Ti/DeliveryCalculator
/home/teddy/Documents/works/fontaineind/app/code/Ti/EmailPrint
/home/teddy/Documents/works/fontaineind/app/code/Ti/Justsale
/home/teddy/Documents/works/fontaineind/app/code/Ti/RangeCompatible
/home/teddy/Documents/works/fontaineind/app/code/Ti/Sales
/home/teddy/Documents/works/fontaineind/app/code/Ti/StoreLocation
/home/teddy/Documents/works/fontaineind/app/code/Ti/ZeroDecimal
/home/teddy/Documents/works/fontaineind/app/code/Webkul/OutOfStockNotification
/home/teddy/Documents/works/fontaineind/app/code/Webkul/Preorder
/home/teddy/Documents/works/fontaineind/app/code/Webkul/Preorder.zip
/home/teddy/Documents/works/fontaineind/app/code/Webkul/Preorder_new.zip
/home/teddy/Documents/works/fontaineind/app/code/WeltPixel/Backend
/home/teddy/Documents/works/fontaineind/app/code/WeltPixel/CmsBlockScheduler
/home/teddy/Documents/works/fontaineind/app/code/WeltPixel/GoogleCards
/home/teddy/Documents/works/fontaineind/app/design/frontend/Codazon/fastest/baby_kid
/home/teddy/Documents/works/fontaineind/app/design/frontend/Codazon/fastest/bigmarket
/home/teddy/Documents/works/fontaineind/app/design/frontend/Codazon/fastest/drug_pharmacy
/home/teddy/Documents/works/fontaineind/app/design/frontend/Codazon/fastest/ellyana
/home/teddy/Documents/works/fontaineind/app/design/frontend/Codazon/fastest/fashion
/home/teddy/Documents/works/fontaineind/app/design/frontend/Codazon/fastest/fontaine
/home/teddy/Documents/works/fontaineind/app/design/frontend/Codazon/fastest/food_drink
/home/teddy/Documents/works/fontaineind/app/design/frontend/Codazon/fastest/grocery_gourmet
/home/teddy/Documents/works/fontaineind/app/design/frontend/Codazon/fastest/handbag
/home/teddy/Documents/works/fontaineind/app/design/frontend/Codazon/fastest/jewelry
/home/teddy/Documents/works/fontaineind/app/design/frontend/Codazon/fastest/outdoor
/home/teddy/Documents/works/fontaineind/app/design/frontend/Codazon/fastest/sportswear
/home/teddy/Documents/works/fontaineind/app/design/frontend/Codazon/fastest/westylefashion
/home/teddy/Documents/works/fontaineind/app/design/frontend/Codazon/fastest/westylejewelry
/home/teddy/Documents/works/fontaineind/app/design/frontend/Codazon/fastest/registration.php

/home/teddy/Documents/works/sc2/app/code/Advcha/FeaturedCategories
/home/teddy/Documents/works/sc2/app/code/Advcha/FeaturedCategoriesSort
/home/teddy/Documents/works/sc2/app/code/Advcha/Unitprice
/home/teddy/Documents/works/sc2/app/code/Amasty/Base
/home/teddy/Documents/works/sc2/app/code/Amasty/Checkout
/home/teddy/Documents/works/sc2/app/code/Amasty/Geoip
/home/teddy/Documents/works/sc2/app/code/Amasty/Pgrid
/home/teddy/Documents/works/sc2/app/code/Chilly/Productsgrid
/home/teddy/Documents/works/sc2/app/code/Ess/M2ePro
/home/teddy/Documents/works/sc2/app/code/FirstScribe/EmailLogo
/home/teddy/Documents/works/sc2/app/code/IWD/Opc
/home/teddy/Documents/works/sc2/app/code/LitExtension/CartMigration
/home/teddy/Documents/works/sc2/app/code/LitExtension/Core
/home/teddy/Documents/works/sc2/app/code/Magefan/Blog
/home/teddy/Documents/works/sc2/app/code/Mageplaza/Core
/home/teddy/Documents/works/sc2/app/code/Mageplaza/Productslider
/home/teddy/Documents/works/sc2/app/code/Magiccart/Alothemes
/home/teddy/Documents/works/sc2/app/code/Magiccart/Magicmenu
/home/teddy/Documents/works/sc2/app/code/Magiccart/Magicproduct
/home/teddy/Documents/works/sc2/app/code/Magiccart/Shopbrand
/home/teddy/Documents/works/sc2/app/code/Magiccart/Testimonial
/home/teddy/Documents/works/sc2/app/code/Manadev/Core
/home/teddy/Documents/works/sc2/app/code/Manadev/LayeredNavigation
/home/teddy/Documents/works/sc2/app/code/Manadev/ProductCollection
/home/teddy/Documents/works/sc2/app/code/OPG/Square
/home/teddy/Documents/works/sc2/app/code/ShopGo/CheckoutCity
/home/teddy/Documents/works/sc2/app/code/StickerCollective/Design
/home/teddy/Documents/works/sc2/app/code/Strategery/Infinitescroll
/home/teddy/Documents/works/sc2/app/design/frontend/Alothemes/alto2
/home/teddy/Documents/works/sc2/app/design/frontend/Alothemes/alto3
/home/teddy/Documents/works/sc2/app/design/frontend/Alothemes/alto4
/home/teddy/Documents/works/sc2/app/design/frontend/Alothemes/default
/home/teddy/Documents/works/sc2/app/design/frontend/Alothemes/stickercollective

/home/teddy/Documents/works/tff-magento2/app/code/Aitoc/ProductUnitsAndQuantities
/home/teddy/Documents/works/tff-magento2/app/code/Amasty/Base
/home/teddy/Documents/works/tff-magento2/app/code/Amasty/Orderattr
/home/teddy/Documents/works/tff-magento2/app/code/Amasty/Scroll
/home/teddy/Documents/works/tff-magento2/app/code/Amasty/Shopby
/home/teddy/Documents/works/tff-magento2/app/code/Amasty/ShopbyBrand
/home/teddy/Documents/works/tff-magento2/app/code/Amasty/ShopbyPage
/home/teddy/Documents/works/tff-magento2/app/code/Amasty/ShopbyRoot
/home/teddy/Documents/works/tff-magento2/app/code/Amasty/ShopbySeo
/home/teddy/Documents/works/tff-magento2/app/code/Apptrian/ImageOptimizer
/home/teddy/Documents/works/tff-magento2/app/code/CommerceExtensions/ProductImportExport
/home/teddy/Documents/works/tff-magento2/app/code/CyberSolutionsLLC/FlyingFork
/home/teddy/Documents/works/tff-magento2/app/code/CyberSolutionsLLC/InfortisExtended
/home/teddy/Documents/works/tff-magento2/app/code/Firebear/ImportExport
/home/teddy/Documents/works/tff-magento2/app/code/Fox/Seo
/home/teddy/Documents/works/tff-magento2/app/code/Iazel/RegenProductUrl
/home/teddy/Documents/works/tff-magento2/app/code/Ibnab/DeleteOrders
/home/teddy/Documents/works/tff-magento2/app/code/Infortis/Base
/home/teddy/Documents/works/tff-magento2/app/code/Infortis/Brands
/home/teddy/Documents/works/tff-magento2/app/code/Infortis/Cgen
/home/teddy/Documents/works/tff-magento2/app/code/Infortis/Dataporter
/home/teddy/Documents/works/tff-magento2/app/code/Infortis/Infortis
/home/teddy/Documents/works/tff-magento2/app/code/Infortis/Ultimo
/home/teddy/Documents/works/tff-magento2/app/code/Infortis/UltraMegamenu
/home/teddy/Documents/works/tff-magento2/app/code/Infortis/UltraSlideshow
/home/teddy/Documents/works/tff-magento2/app/code/Magenerds/CategoryProductLink
/home/teddy/Documents/works/tff-magento2/app/code/MagePsycho/Easypathhints
/home/teddy/Documents/works/tff-magento2/app/code/MageWorkshop/ShoppingCartNotifications
/home/teddy/Documents/works/tff-magento2/app/code/Mgt/DeveloperToolbar
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/AddressAutocomplete
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/AddressFieldManager
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/Ajaxpro
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/Askit
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/Attributepages
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/Checkout
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/CheckoutCart
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/CheckoutFields
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/CheckoutSuccess
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/Core
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/DeliveryDate
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/Easyflags
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/Firecheckout
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/Geoip
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/Highlight
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/Maintenance
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/Orderattachment
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/Reviewreminder
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/RichSnippets
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/SlickCarousel
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/SubscriptionChecker
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/Suggestpage
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/Taxvat
/home/teddy/Documents/works/tff-magento2/app/code/Swissup/Testimonials
/home/teddy/Documents/works/tff-magento2/app/code/Ubertheme/Ubdatamigration
/home/teddy/Documents/works/tff-magento2/app/code/Vsourz/OrderSuccess
/home/teddy/Documents/works/tff-magento2/app/code/WeltPixel/Backend
/home/teddy/Documents/works/tff-magento2/app/code/WeltPixel/GoogleTagManager
/home/teddy/Documents/works/tff-magento2/app/code/Meanbee.tar.gz
/home/teddy/Documents/works/tff-magento2/app/design/frontend/Infortis/base
/home/teddy/Documents/works/tff-magento2/app/design/frontend/Infortis/ultimo
/home/teddy/Documents/works/tff-magento2/app/design/frontend/Infortis/updated

/home/teddy/Documents/works/scm/app/code/Advcha/ShopbyBikes
/home/teddy/Documents/works/scm/app/code/Advcha/UsedMotorcycles
/home/teddy/Documents/works/scm/app/code/SCM/HelloWorld
/home/teddy/Documents/works/scm/app/code/SCM/ModuleSearch
/home/teddy/Documents/works/scm/app/code/SCM/SCMWidget
/home/teddy/Documents/works/scm/app/code/Ves/All
/home/teddy/Documents/works/scm/app/code/Ves/Autosearch
/home/teddy/Documents/works/scm/app/code/Ves/BaseWidget
/home/teddy/Documents/works/scm/app/code/Ves/Blog
/home/teddy/Documents/works/scm/app/code/Ves/Brand
/home/teddy/Documents/works/scm/app/code/Ves/Megamenu
/home/teddy/Documents/works/scm/app/code/Ves/PageBuilder
/home/teddy/Documents/works/scm/app/code/Ves/Productlist
/home/teddy/Documents/works/scm/app/code/Ves/Setup
/home/teddy/Documents/works/scm/app/code/Ves/Testimonial
/home/teddy/Documents/works/scm/app/code/Ves/Themesettings
/home/teddy/Documents/works/scm/app/design/frontend/M2themes/ceramix
/home/teddy/Documents/works/scm/app/design/frontend/M2themes/coolstuff
/home/teddy/Documents/works/scm/app/design/frontend/M2themes/evolution
/home/teddy/Documents/works/scm/app/design/frontend/M2themes/kitchen
/home/teddy/Documents/works/scm/app/design/frontend/M2themes/m2theme_child
/home/teddy/Documents/works/scm/app/design/frontend/SCM/Minimal

/home/teddy/Documents/works/ayoimport-dev.com/app/code/Advcha/SGApi
/home/teddy/Documents/works/ayoimport-dev.com/app/code/AyoImport/AdminCategoryProductThumbnail
/home/teddy/Documents/works/ayoimport-dev.com/app/code/AyoImport/ApiVendor
/home/teddy/Documents/works/ayoimport-dev.com/app/code/AyoImport/BulkProductCat
/home/teddy/Documents/works/ayoimport-dev.com/app/code/AyoImport/Productsgrid
/home/teddy/Documents/works/ayoimport-dev.com/app/code/AyoImport/ProductTags
/home/teddy/Documents/works/ayoimport-dev.com/app/code/AyoImport/ProductTaxRates
/home/teddy/Documents/works/ayoimport-dev.com/app/code/AyoImport/SGProductImage
/home/teddy/Documents/works/ayoimport-dev.com/app/code/AyoImport/SGProductImageCategory
/home/teddy/Documents/works/ayoimport-dev.com/app/code/Magefan/Blog
/home/teddy/Documents/works/ayoimport-dev.com/app/code/Magefan/Community
/home/teddy/Documents/works/ayoimport-dev.com/app/code/Sm/BackEnd
/home/teddy/Documents/works/ayoimport-dev.com/app/code/Sm/CartQuickPro
/home/teddy/Documents/works/ayoimport-dev.com/app/code/Sm/Categories
/home/teddy/Documents/works/ayoimport-dev.com/app/code/Sm/CategoriesMenu
/home/teddy/Documents/works/ayoimport-dev.com/app/code/Sm/FilterProducts
/home/teddy/Documents/works/ayoimport-dev.com/app/code/Sm/ListingTabs
/home/teddy/Documents/works/ayoimport-dev.com/app/code/Sm/Market
/home/teddy/Documents/works/ayoimport-dev.com/app/code/Sm/MegaMenu
/home/teddy/Documents/works/ayoimport-dev.com/app/code/Sm/SearchBox
/home/teddy/Documents/works/ayoimport-dev.com/app/code/Sm/ShopBy
/home/teddy/Documents/works/ayoimport-dev.com/app/design/frontend/Sm/market
/home/teddy/Documents/works/ayoimport-dev.com/app/design/frontend/Sm/market_child
/home/teddy/Documents/works/ayoimport-dev.com/app/design/frontend/Sm/market_mobile

Composer

I got a fews problem when I tried to check the composer version. A few warnings:

Solution:
ref: https://stackoverflow.com/questions/35874482/cannot-create-cache-directory-or-directory-is-not-writable-proceeding-withou

 

PHP 7.2 FPM AND NGINX

From http://myprojects.advchaweb.com/index.php/2018/06/25/symfony-4-blog-app/

I NEED TO CHECK MY PHP VERSION. CLI ALREADY 7.2.

BUT THE SERVER STILL 7.0 (http://localhost/phpinfo.php).
IF NOT, CHANGE THE PHP-CLI FROM PHP7.0 (FOR EXAMPLE) TO PHP7.2:

I ALREADY HAS 7.2 BUT SOME EXTENSIONS ARE MISSING. SO INSTALL THEM

TO ENABLE PHP 7.2 ON APACHE2 SERVER, PLS DO (MAKE SURE NGINX IS STOPPED IF IT’S RUNNING AND START APACHE2):

TEST: http://localhost/phpinfo.php

IF NEEDED TO CHANGE THE PHP SETTING, PLS EDIT:

TO ENABLE PHP 7.2 ON NGINX SERVER, PLS DO (MAKE SURE APACHE2 IS STOPPED IF IT’S RUNNING AND START NGINX):

THE NGINX MAIN CONFIG IN /etc/nginx/nginx.conf
THE DEFAULT VIRTUALHOST IN /etc/nginx/sites-available/default
EDIT IT TO ENABLE PARSING PHP FILE:

CHANGE THE CONTENT TO ENABLE PHP 7.2 FPM:

THEN CHANGE PHP7.2-FPM SETTING:

CHANGE THE CONTENT:

THEN RESTART PHP7.2-FPM SERVICE:

CHECK NGINX SYNTAX: sudo nginx -t
RESTART NGINX: sudo systemctl restart nginx
OPEN IT: http://localhost/phpinfo.php (NEED TO CLEAR THE BROWSER CACHE FIRST)

Symfony 4 – Blog App

Ref: https://auth0.com/blog/symfony-tutorial-building-a-blog-part-1/
https://symfony.com/doc/current/setup.html

Install the latest Symfony 4 via Composer with the following command:

Update DotEnv File
In your root directory, there is a file called .env (usually this file is hidden. so set your system to show the hidden files), you should see something similar to the following:

Change to this:

run the following command

which will create a database with the value of your database name.
<!– START SKIP –>
IF YOU GOT ERROR LIKE MINE. IT’S BECAUSE MY PHP SETTING & APACHE2/NGINX SERVER DIDN’T WORK WELL. SKIP IT IF YOU DONT HAVE ANY ERROR LIKE THIS :

I NEED TO CHECK MY PHP VERSION. CLI ALREADY 7.2.

BUT THE SERVER STILL 7.0 (http://localhost/phpinfo.php). I ALREADY HAS 7.2 BUT SOME EXTENSIONS ARE MISSING. SO INSTALL THEM

TO ENABLE PHP 7.2 ON APACHE2 SERVER, PLS DO (MAKE SURE NGINX IS STOPPED IF IT’S RUNNING AND START APACHE2):

TEST: http://localhost/phpinfo.php

IF NEEDED TO CHANGE THE PHP SETTING, PLS EDIT:

TO ENABLE PHP 7.2 ON NGINX SERVER, PLS DO (MAKE SURE APACHE2 IS STOPPED IF IT’S RUNNING AND START NGINX):

THE NGINX MAIN CONFIG IN /etc/nginx/nginx.conf
THE DEFAULT VIRTUALHOST IN /etc/nginx/sites-available/default
EDIT IT TO ENABLE PARSING PHP FILE:

CHANGE THE CONTENT TO ENABLE PHP 7.2 FPM:

THEN CHANGE PHP7.2-FPM SETTING:

CHANGE THE CONTENT:

THEN RESTART PHP7.2-FPM SERVICE:

CHECK NGINX SYNTAX: sudo nginx -t
RESTART NGINX: sudo systemctl restart nginx
OPEN IT: http://localhost/phpinfo.php (NEED TO CLEAR THE BROWSER CACHE FIRST)
<!– END SKIP –>

OK. I FIXED THE CREATION DATABASE ERROR. RUN AGAIN

HERE IS THE WORKING RESULT:

Create the Blog Controller
Create new BlogController by running the following command

When it asks for The class name of the controller to create, type in: BlogController.

THEN CHANGE THE ROUTE IN src/Controller/BlogController.php
FROM:

TO:

THEN TEST IT VIA SYMFONY WEB SERVER. RUN:

OPEN IT ON YOUR BROWSER: http://127.0.0.1:8000
THEN you’ll be shown a Hello BlogController! page.

Creating a New Author Entity
Create new Author entity by running the following command:

OPEN A PHP FILE  src/Entity/Author.php, THEN REPLACE IT.
FROM:

TO:

Creating a New BlogPost Entity
Create new BlogPost entity by running the following command php

When it asks for The class name of the entity to create, type in: BlogPost.

Once the command has finished running, you’ll find a new file in src/Entity called BlogPost.php. Open this and configure it like so:

Although you have created these entities, your database still has no tables in there. Based off these entities, Doctrine can create the tables we’ve specified. In order to do this, all you have to do is run:

Install Doctrine-Fixtures
We want to just populate some data into the newly created tables as examples during the creation of the blog. So install doctrine-fixtures.

Create Author and BlogPost Fixtures
Create a new file (and the directories the file is stored in) under src/DataFixtures/ORM/Fixtures.php and insert the following into the file:

Running Fixtures
Let’s run the fixtures! php bin/console doctrine:fixtures:load

 

Pemakaian Generator Yamaha ET-1

Ref: http://pasargenset.com/jual-genset-yamaha-et-1-harga-murah-maluku.html

Deskripsi Genset YAMAHA ET 1

Genset YAMAHA ET 1 adalah Genset Yamaha yang Termurah, satu satunya Generator Set 2 Tak kualitas YAMAHA JEPANG. Hadir dengan Suara yang tidak berisik, ringan dan irit Bahan Bakar. Keunggulan Genset 2 Tak YAMAHA ET 1 adalah Perawatannya yang Mudah, Bahan Bakarnya menggunakan Bensin Campur Oli. Untuk pengoperasionalan Genset YAMAHA ET 1 ini menggunakan Manual Recoil Starter. Dengan Daya Output sekitar 650 Watt dan Daya Maksimum di 780 Watt, Genset YAMAHA ET 1 cocok digunakan di Rumahan, untuk Kondisi Darurat menyalakan Lampu atau Alat Elektronik lainnya. Bisa juga untuk Pengerjaan Luar yang tidak membutuhkan daya listrik yang besar. Seluruh Produk Generator YAMAHA telah lulus uji ISO 8528. Genset YAMAHA ET 1 merupakan Produk Genset YAMAHA Termurah Kualitas Bagus dengan Jaminan Garansi 1 Tahun.

Spesifikasi Detail GENSET YAMAHA ET 1
MODEL
Genset YAMAHA ET

AC Volt / Frekwensi
220v / 50 Hz
Daya Rata rata
650 W
Daya Maksimum
780 W
MESIN
Model
2 ST ( 2 Tak )
Pengatur Tegangan
Condenser
Kapasitas Mesin
63 cc
Kapasitas Tangki Bahan Bakar
4 L
Bahan Bakar
Bensin Campur Oli
Sistem Start
Recoil
Waktu Pengoperasian
6 Jam
Tingkat Kebisingan (7m)
57 dBa
Dimensi dan Berat
Non Paking Kayu
P: 367mm x L : 312mm x T : 376 mm Berat : 19 Kg
Paking Kayu
P: 420mm x L : 360mm x T :  430 mm Berat : 30 Kg
Warranty
1 Year

Petunjuk Penggunaan:

Sebelum di hidupkan (di engkol), Ubah saklar power to ON, kemudian choke depan di geser ke maksimal (kiri??/kanan). kemudian choke samping/minyak di putar ke posisi ON (bawah). tarik tuas engkol untuk menghidupkan genset. tarik tuas engkol berulang-ulang sampai hidup. Pastikan bahan bakar bensin masih ada. Setelah genset hidup, pasang kabel power yang diperlukan peralatan elektronik anda.

Untuk mematikan genset, jangan diubah saklar power to OFF dahulu! Jika ini dilakukan, genset akan susah hidup kedepannya karena ada minyak dibagian bawah yang belum habis terbakar. Cara yang baik untuk mematikan genset adalah, geser choke ke posisi minimal (kanan??/kiri). Ingat, kabel power sudah dilepas dari genset. kemudian biarkan genset hidup beberapa saat. Genset akan mati sendiri dan saklar power bisa di ubah ke OFF dan choke samping/minyak di putar ke posisi OFF (atas).

Penambahan bahan bakar bensin. Pada genset ini bensin di campur dengan oli 2 tak. Pada tutup bahan bakar genset, ada takaran oli 2 tak yang diperlukan untuk mencampur bensin. Ada 4 garis pedoman di tutup tersebut. Ini menunjukkan maksimum 4 liter bensin pada genset ini. Tiap garis menunjukkan berapa banyak oli yang diperlukan tergantung banyak bensin. Jika ingin memasukkan 2 liter bensin, maka isi tutup bahan bakar dengan oli 2 tak sampai penuh 2 garis. Pasang kembali tutup bahan bakar sambil memasukkan oli di dalam tutup tersebut ke bensin.

PERHATIAN: Genset harus diletakkan di luar ruangan dengan sirkulasi udara yang baik. Karena asap dari genset sangat tidak sehat!
Sebaiknya genset dihidupkan sebentar saja sekali seminggu/dua minggu walau tidak digunakan supaya mudah dinyalakan kalau lagi dibutuhkan
jangan lupa selalu sedia bahan bakar (saya pakai pertamax 92) di dalam dirijen sebagai cadangan.

Ionic Framework on Ubuntu 16.04

Ref: https://ionicframework.com/docs/intro/installation/
Make sure node already installed

Installation

Check the ionic version

Check the cordova version

Create a test ionic project

Run the project

New Project
ref: https://ionicframework.com/docs/intro/tutorial/

Go to the project and run

 

Interview with Kristiyan Karadjov

website: http://pethome.bg/
benchmark: https://www.pets4homes.co.uk/

the search page style include distance like on the left sidebar of https://www.pets4homes.co.uk/search/also use ajax to load the search result when the distance slider is moving???

at home page search by cities like olx (autocomplete cities on the search box). currently no autocompleteChange like this:

remove the image border for the gallery and search result like https://www.pets4homes.co.uk/search/

make the registration form/posting form the city field is required
for example: http://pethome.bg/index.php?page=item&action=item_add

make the website responsive (the categories style on homepage)

make the ajax run faster on the search sidebar (change the input) and homepage search –> Use VPS instead

on edit advert/post. make sure all input including ‘vaccinated’ input can be changed. for example http://pethome.bg/index.php?page=item&id=180

something about image gallery on the post detail page (http://pethome.bg/index.php?page=item&id=180#group-3). what is the task??