The latest industry news, interviews, technologies, and resources.
Business
Laravel is one of the most popular PHP web application frameworks. It offers a robust and flexible routing system that allows developers to define and manage application URLs effortlessly. In this blog, we'll dive deep into Laravel routes, exploring the fundamental concepts, types of routes, and best practices for working with them.
Routes are a fundamental part of web development. They define the entry points to your application, mapping URLs to specific controllers and actions. Simply put, routes determine how your application responds to HTTP requests.
To define routes in Laravel, you primarily work with the web.php and api.php files, located in the project's route folder. These files contain route definitions using Laravel's expressive routing methods.
Here's a basic example of defining a route in Laravel:
In this example, we're defining a route that responds to the GET request at the /welcome URL with a simple text response.
Laravel allows you to capture and work with route parameters easily. For example:
In this case, the {id} placeholder captures the value from the URL, making it accessible as a parameter in the route's closure.
The router allows you to register routes that respond to any HTTP verb:
When defining multiple routes that share the same URI, routes using the get, post, put, patch, delete, and options methods should be defined before routes using the any, match, and redirect methods. This ensures the incoming request is matched with the correct route.
Named routes provide a convenient way to reference routes by name rather than their URLs. This is particularly useful when generating links or redirects. To define a named route, use the name method:
You can then generate URLs for named routes using the route function:
Middleware is a powerful feature in Laravel that allows you to filter HTTP requests entering your application. You can attach middleware to routes, making it easy to perform tasks like authentication, authorization, logging, and more.
Route groups allow you to apply middleware, prefixes, and namespaces to a group of routes, making it easier to organize and manage routes for specific parts of your application.
Middleware are executed in the order they are listed in the array.
Cruddy by Design is a software development philosophy or approach that emphasizes simplicity and efficiency in creating CRUD (Create, Read, Update, Delete) operations for database-backed applications. These operations are fundamental to many software applications, especially those that involve data management.
Instead of defining all of your request-handling logic as closures in your route files, you may wish to organize this behavior using "controller" classes. Controllers can group related request-handling logic into a single class.
These were mentioned by Adam Wathan in his Laracon conference. We follow the rules mentioned by him in our code. Let us checkout the rules:
Let's say you have a podcasts application and each podcast contains episodes. If you want to create a route to retrieve the episodes of an individual podcast, it might look like this. It will be a nested resource. So, which controller will be used to perform the necessary action? Let's take a look.
We can see that /podcasts are at the top level. So, to perform nested index actions, the first thought might be to use the PodcastsController. But, if we use PodcastsController for that, we end up defining custom actions that aren't part of the CRUD actions mentioned above. We always want to have the CRUD actions and not custom actions. So, this isn't a good approach. Let's think of other approaches.
We already have an EpisodesController responsible for handling various actions related to episodes, such as listing episodes, displaying episode details, editing episodes, and updating episodes.
Since the above action should give the list of episodes for the given podcast, you might be tempted to point the route to EpisodesController@index.
But here's where the problem comes in, the EpisodesController@index lists all episodes across all podcasts. So to fix that, you need to pass $id as a parameter to the function in the controller and check if it is null and proceed to perform
Here we are reusing the same EpisodesController@index twice and the use cases are different. They don't have anything in common as they load different models, and return different views,
That usually looks like this in a routes file:
Let's take a look at the controller:
This doesn't simplify the code, instead, it complicates it even more by using the same controller for two different actions. So, this method isn't good as well.
If we iterate over the list of standard actions, the index is the most suitable action for our case. We need the index of individual podcast episodes. So, let's create a new PodcastEpisodesController.
Here's the PodcastEpisodesController:
If you have any other routes related to episodes nested under podcasts resource, their actions can also be handled by PodacastEpisodesController.
Each podcast might have a cover image, title, created date etc. as its properties. Let's take a look at the cover image of a podcast.
Here's the endpoint:
If you look at the endpoint, it is pretty clear that the action isn't standard CRUD action. If you iterate over the CRUD actions, the update is the fitting one. For updating an image, all we are doing is updating a field on the podcasts table.
You might think that what we are doing here is an "update" action against our podcasts resource, but it already has an update action which is updating the title,description and website and it doesn't include the cover image. They hit different end points as well. So what should we do?
Here we are using two forms to update the podcast properties:
In cases like these, it is better to use separate controllers for each.
So instead of making a POST request to update-cover-image, let's make a PUT request that treats the cover image like its own resource:
Since it is a podcast application, you can subscribe to the podcasts you like and unsubscribe if you lose interest in them. Let's look at how it's being handled.
So, we need to look at PodcastsController@subscribe and PodcastsController@unsubscribe. Here are the endpoints:
Where does subscribing fit in the CRUD operations we have? It would fit in the store, since we would be storing the podcast if subscribed else we will be deleting that. Let's create a new controller called Subscription Controller. Then the endpoint would be:
If we were using the podcast controller, we were using the id as the route parameter which is not available here. So, we have to send the id as a request.
In the above implementation, the attack method associates the podcast with the user by creating a new record in the podcast_user table. And each of this record has an id. So, if we rename podcast_user to subscriptions, we can also create a model for working with the table directly called Subscription.
Since this table has foreign keys back to users and podcasts, we could even define those as belongsTo relationships on the new model:
Instead of using the attach method, we can just create a new subscription.
So, for unsubscribing,
The last custom actions we have are PodcastsController@publish and PodcastsController@unpublish.Here are the endpoints:
Again, they are not in standard CRUD, since we update published_at column, one possiblity is to use PodcastsController@update for it. But similar to Episodes, doing two different actions in one complicates the code. So, create a dedicated PublishedPodcastController.
In these situations, it can often be helpful to think of a resource in a certain state as it's own independent resource.
Just like subscribe, if publish becomes creating a published podcast, then unpublish could become destroying a published podcast.
So, here's what the PublishedPodcastsController looks like:
Laravel routes are a vital component of building web applications. They provide a clear and efficient way to define how your application responds to various HTTP requests. With features like route parameters, named routes, middleware, and route groups, Laravel offers a comprehensive and flexible routing system that simplifies the development process.
https://www.youtube.com/watch?v=MF0jFKvS4SI&list=LL&index=1&ab_channel=AdamWathan
Business
Email is a fundamental tool for communication. Whether you are conducting business negotiations, marketing a product, or even receiving automated notifications, email is at the core of these interactions. However, not all email-sending methods are created equal and each method has its strengths and weaknesses, and the right choice depends on your unique needs. In this blog, we'll explore the different options mentioned below and make an informed choice based on a project's specific needs.
According to Yes Lifecycle Marketing, 2019, the average email open rate is 20.81%. So, when an email is sent from your organization, the first thing to ensure is that it doesn't land in the spam folder. For this, the services mentioned above such as Resend, and SendGrid are used.
Personalization is the key along with an appropriate preview and subject line to attract the customer's attention and stand out amongst the other mails in the inbox. Once you start personalizing your email, you will see the incredible impact it has. Emails with personalized subject lines generate 50% higher open rates.
So, a great email marketing tip would be to customize your greeting and subject line to include individual names when you send out emails. You can also try personalizing your emails with the company’s name, industry, or topic of interest.
React Email provides a set of unstyled components through which you can personalize the email being sent. This allows developers to build emails using a component-based architecture similar to React web apps. It aims to modernize the process of email development by leveraging React's syntax, TypeScript, and integrating with modern frontend tools. This provides a better developer experience compared to traditional solutions and enables developers to build beautiful, scalable email templates. React email also consists of example templates that can be tweaked as per requirements.
React email provides various components that are similar to the components of HTML which makes it easier due to the familiarity with the syntax. The list of the components is provided here on the official website. You can either install a specific component or install all the components at once using the following command:
The template of your email can be designed and modified based on the content and requirements of the mail. Let us consider a simple email thanking a customer for using our service.
In the above code, we define a TypeScript interface, _91BytesThankYouEmailProps, with a userName and userMail fields. This interface specifies the structure of the props that our _91BytesThankYouEmail component is expected to receive. If no user name is provided when the email is sent, the variable userName is initialized with a default value of “Customer”.
To use React Email with any email service provider, we first need to convert the components made with React into an HTML string. This is done using the render utility. To render it into HTML form, first install it using the command:
The component can be rendered using:
Now that we have the email template and it is rendered, we can start sending the email through a service provider. The service providers that can be integrated with React email are Resend, SendGrid, and Nodemailer. All these service providers use their own SMTP servers. Let us know more about SMTP servers in detail.
Behind the scenes, SMTP servers play a crucial role in ensuring that your emails are sent and received seamlessly. SMTP stands for Simple Mail Transfer Protocol, and an SMTP server is a specialized computer program or server responsible for sending, receiving, and routing emails between different email clients and servers.
SMTP servers follow a series of steps to deliver your email from sender to recipient:
Creating your own SMTP server can be a complex process and we can use the existing SMTP servers for our usage.
Nodemailer is a popular and widely used Node.js library for sending emails. It's flexible, easy to use, and supports various email providers and protocols. With Nodemailer, you can send text emails, HTML emails, attachments, and more, making it a versatile choice for both simple and complex email-sending tasks.
Before diving into how to use Nodemailer, let's understand why it's a popular choice for sending emails:
Now, let's get into the practical details of using Nodemailer.
To use Nodemailer, you'll need to install it as a dependency in your Node.js project. Run the following command in the terminal:
Nodemailer requires some configuration to work correctly. Here's an example configuration for sending emails through a Gmail account:
Replace 'yourMail@gmail.com' and 'yourAppPassword' with your Gmail email address and app-specific password. Note that using your email password directly in your code isn't a secure practice for production applications. In production, you should use environment variables to store sensitive information securely.
Once you've configured Nodemailer, sending an email is straightforward. Here's a basic example:
In this example:
You can customize the email's content by modifying the mailOptions object. Nodemailer also supports sending HTML content, attachments, and more advanced features.
In our example, we will also be sending an email from the node server. To do this, expose an API endpoint from your Node server that your React app can call to send emails when a form is submitted. The data sent from the React app consists of HTML and JSON data. The HTML data consists of the email template which is denoted by emailHtml and the JSON data consists of the receiver's details such as name and email ID denoted by jsonData.
Here we are using the SMTP server provided by the gmail itself. You can integrate nodemailer with resend as well. If integrated with Resend, API_KEY of resend is used along with the SMTP server of resend.
SendGrid is an email delivery platform that offers a suite of tools and services designed to simplify email management and enhance deliverability. Founded in 2009, SendGrid has grown into one of the leading email delivery services, trusted by businesses and developers worldwide.
Key Features of SendGrid
In your Node.js project directory, open a terminal and run the following command to install the SendGrid package:
To use SendGrid, you need to create an account first. Head over to the website to create one. Then click on Create Identity. This is how the receivers will see the mail. Then fill in the details in the form.
Click on create after filling out the form. Then verify the sender. You will receive an email to the email address mentioned in the from section in the form. You can verify by clicking on the verify Single Sender button. Once verification is done, head over to the API keys in the settings section and create the API key. Choose the permissions based on your requirements.
Copy the API key once you create it. Now you can send emails using this API key.
Add your API key to the env file. Let's send the Thank you mail using SendGrid.
As we discussed before, one of the problems with sending marketing or business mail is the risk of the mail landing in the spam folder. Resend is an email service that prevents this from happening. It is quick and easy to set up. Similar to SendGrid, an API key is needed to send the mail. It can be integrated with Nodemailer too.
Let us continue with the Thank You email with Nodejs and Express being the server. We will be using the same email template that we created before.
You can install resend with the following command:
To get the Resend API key, create a Resend account, click on Add and API key and copy the key as soon as you create it as it is only available once. You can check the emails sent and received in the Emails section.
If you observe the email template, the from email address is mentioned as 'onboarding@resend.dev' can be used to send the testing mail but not during production. So, add your domain and verify the DNS to start sending emails.
Resend requires some configuration to work correctly. Here's an example configuration for sending emails:
Once you've configured Resend, sending an email is simple. Here's how we will be sending the Thank You mail.
Always place your API keys in the env file. One of the key benefits of using an env file is the separation of configuration from the code. This means that sensitive information like API keys, database credentials, and other configuration settings are kept separate from the source code. This makes it easier to manage configuration settings and maintain security.
The choice between Nodemailer, SendGrid, and Resend depends on your specific needs and priorities:
Ultimately, the best choice depends on your project's specific requirements, development stack, and email marketing goals. You may also consider factors such as pricing, scalability, and the level of support provided by each service when making your decision.
Cover image by Stephen Phillips - Hostreviews.co.ukUnsplash
Increase icons created by IconLauk - Flaticon
https://blog.logrocket.com/streamline-email-creation-react-email/
Business
Any application you use these days often interacts with a database. A database is at the core of a large-scale application. To store large amounts of data and retrieve them efficiently, speed matters, especially in these times when things have to be done quickly.
Laravel makes interacting with databases extremely simple across a variety of supported databases using raw SQL, a fluent query builder, and the Eloquent ORM. Currently, Laravel provides first-party support for five databases:
Raw SQL, Query Builders and ORMs are the three common approaches for accessing data from a database. This blog will cover the three approaches along with the advantages and disadvantages of each approach. Here is a tabular view of the strengths and weaknesses of each approach.
The more advanced a query, the better it is to use fewer abstractions, with SQL having no abstraction, Query Builder having some level of abstraction and ORMs having the highest level of abstraction.
As the name suggests, we directly interact with the database using SQL queries. Let's take a look at the advantages and disadvantages:
Let's check out some queries using raw SQL.
Select statements are used to select/retrieve data from the database. Let's take an example where we have the following tables - orders,order_details,products,and customers and perform some queries on them.
Let's consider an example:
We need to get a list of products along with their total sales, the total sales being in descending order. We have tables containing the data of orders with the name order_details and tables containing products with the name products.
Let's break it into smaller parts. Then this would be the list of tasks we need to perform in order:
Let's see another query:
We need to retrieve a list of orders along with the names of the customers who placed them and the names of the products that were ordered. The orders should have an order date after January 1, 2022.
Again let's break it into smaller parts. Then this would be the list of tasks we need to perform in order:
Now add the where condition to get the orders that have an order date after January 1, 2022.
These queries are used to insert the data into the table. The insert queries can be combined with the select queries to select data from another table and insert it into the table required.
Let's consider a situation where you have a users table, but you want to create another table for premium users in the users table called premium_users and insert the premium users' records into that table.
Let's look at another example:
We need to insert data into the clients table based on data from the suppliers table and ensure that only new clients (those that don't already exist in the clients table) are inserted.
We need to select the data from the suppliers table and then apply an additional condition that prevents from selecting the clients that already exist, for this we will use WHERE NOT EXISTS clause.
In case you are wondering what a query builder is, it is an interface that allows developers to construct database queries more abstractly instead of using raw SQL statements. This makes it more readable and easy to interact with the database. Let's take a look at the documentation:
Laravel's database query builder provides a convenient, fluent interface for creating and running database queries. It can be used to perform most database operations in your application and works perfectly with all of Laravel's supported database systems.
It means that Laravel provides a fluent way to construct and execute database queries. It allows you to chain methods, and execute complex methods with ease and makes your code more readable and maintainable. One of the advantages of using Laravel's query builder is protection against SQL injections. For this Laravel uses the PDO parameter and it doesn't support binding column names, which means that you should never take column names as input from the user.
Let's consider an example:
The tables we have are orders,customers and products whose schema is given below.
Let's consider the following query:
We need to retrieve information about the total sales for each customer.
Let's break it into smaller parts.
Laravel's Query Builder provides an insert method that can be used to insert records into the table. The insertOrIgnore method will ignore errors while inserting records into the database. The insertUsing method will insert new records into the table while using a subquery to determine the data that should be inserted.
Let's take an example
Let's insert data from users table into another table called pruned_users given that the users updated_at column is less than or equal to one month ago.
We need to insert the values of id,name,email into the pruned_users from the users table. We will be using the insert_using method since we need to apply a condition to determine which data should be inserted into pruned_users table. This will be the subquery.
In the subquery, we need to select id,name,email from the users table with the condition that updated_at is less than a month, for which we will use where method.
Laravel includes Eloquent, an object-relational mapper (ORM) that makes it enjoyable to interact with your database. When using Eloquent, each database table has a corresponding "Model" that is used to interact with that table. In addition to retrieving records from the database table, Eloquent models allow you to insert, update, and delete records from the table as well.
Complex relationships in Eloquent ORM can involve multiple levels of hasMany and belongsTo relationships between models.
Let's consider an example involving three related models: Author, Book, and Chapter. Each author can have multiple books, and each book can have multiple chapters. We'll set up these relationships to demonstrate complex relationships in Eloquent.
Author Model
Book Model
Chapter Model
With these models, we have set up the following relationships:
Let's consider the following example:
We need to fetch the list of users along with their associated posts, including columns like name, email, title, and created_at.
Let's checkout User Model and Post Model. The User model should have hasMany relationship to show that a user has multiple posts.
The Post Model should have a belongsTo relationship to associate each post with a user.
Now, we need to select the user and post details after joining them on id column.
If we want to create a new user, then the create method automatically creates a new record in the users table with the specified data and returns the created user model instance, which is then assigned to the variable $user.