<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bearveloper 🐻</title>
    <description>The latest articles on DEV Community by Bearveloper 🐻 (@bearveloper).</description>
    <link>https://dev.to/bearveloper</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F900200%2F534a9f74-a781-43c7-84db-d23bee742640.jpg</url>
      <title>DEV Community: Bearveloper 🐻</title>
      <link>https://dev.to/bearveloper</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bearveloper"/>
    <language>en</language>
    <item>
      <title>Thoughts about Twitter and the migration to Mastodon</title>
      <dc:creator>Bearveloper 🐻</dc:creator>
      <pubDate>Sun, 06 Nov 2022 19:18:57 +0000</pubDate>
      <link>https://dev.to/bearveloper/thoughts-about-twitter-and-the-migration-to-mastodon-1jpj</link>
      <guid>https://dev.to/bearveloper/thoughts-about-twitter-and-the-migration-to-mastodon-1jpj</guid>
      <description>&lt;p&gt;I usually don't stress thinking or having an opinion about what others do or think. My motto in these cases is mostly &lt;em&gt;you do you&lt;/em&gt;, but with the recent actions taken by Elon Musk, one has to stop and think a bit about it. I do not care what he does with his money. If he wants to buy Twitter, Facebook, or the corner store, I don't care. The problem to me begins when he starts firing employees, allegedly after questionable reasons like the number of lines of code, ideology, and who knows what else. Many of the fired employees were in charge of the moderation tools, so as soon as this happened, thousands –if not millions at this point– of tweets with aggressive, racist, transphobic, etc. content started to propagate the social network. That is not cool. Yes, you have the right to express your opinion, but there must be a limit, and to me, that limit is when you cross the line and disrespect, insult, or attack others. That, to me, is not free speech. That is abusive speech.&lt;/p&gt;

&lt;p&gt;Mastodon has been around for a while. I discovered it in a previous Twitter migration circa 2018. Like many, this past week, I had to learn new concepts, search for instances, try different clients, and eventually install and run my server. It did not stick. After a few months terminated my instance and moved on. But that is not the end of the story. I have been in and out of Mastodon many times and on many servers. I still have a few –redirected– accounts today that I used in the past. Still, this time and thanks to the massive attraction Mastodon gained, I have posted more statuses than ever and am currently growing my network. Many ask if this will be just another fluke or if this will be another WhatsApp to Telegram attempt. My answer is no, it might not make Twitter go bankrupt, but it will stick with many people. Why do I think this? Because I've seen lots of messages that agree with me, some like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I have posted more in Mastodon in the last few days than I ever did all these years on Twitter.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Or:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Everyone is so welcoming here! Love it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And also:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It feels so good to be in Mastodon. It has a '90s vibe where everyone is nice, and there is no algorithm driving what I read.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, yes, many of those 250K+ new users will not stick around after a while, but many will and those will share their experiences with the rest of the world.&lt;/p&gt;

&lt;p&gt;Mastodon is now visible and in many users' mouths (and fingers).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Welcome to the Fediverse!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>writing</category>
    </item>
    <item>
      <title>WPBakery Developer Documentation</title>
      <dc:creator>Bearveloper 🐻</dc:creator>
      <pubDate>Fri, 28 Jan 2022 16:39:49 +0000</pubDate>
      <link>https://dev.to/bearveloper/wpbakery-developer-documentation-136f</link>
      <guid>https://dev.to/bearveloper/wpbakery-developer-documentation-136f</guid>
      <description>&lt;p&gt;If you work with WordPress and &lt;a href="https://wpbakery.com/"&gt;WPBakery&lt;/a&gt; (also known by some as Visual Composer) chances are you have had to develop a custom shortcode element. Although I think WPBakery is a pretty good developer tool, their docs are far from being the best ones, and they are sometimes pretty hard to find.&lt;/p&gt;

&lt;p&gt;To save myself (and you) some research time, here are some developer links I use a lot:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kb.wpbakery.com/docs/inner-api/"&gt;Inner API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kb.wpbakery.com/docs/inner-api/vc_map/"&gt;vc_map&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>php</category>
      <category>visualcomposer</category>
      <category>wordpress</category>
    </item>
    <item>
      <title>Codes of Conduct</title>
      <dc:creator>Bearveloper 🐻</dc:creator>
      <pubDate>Sun, 21 Feb 2021 12:37:43 +0000</pubDate>
      <link>https://dev.to/bearveloper/codes-of-conduct-5bf9</link>
      <guid>https://dev.to/bearveloper/codes-of-conduct-5bf9</guid>
      <description>&lt;p&gt;I am a big fan of having, following, and enforcing a Code of Conduct (CoC) in all projects where I participate. If by any chance they do not have one, I always seek to collaborate with the project maintainers to adopt one that aligns properly with their values. So far I have seen great results, we all grow together, and ensure a safe and civilized space for everyone.&lt;/p&gt;

&lt;p&gt;My favorite Code of Conduct, is &lt;a href="https://www.contributor-covenant.org"&gt;Contributor Covenant&lt;/a&gt;. It is pretty easy to understand, pretty easy to implement, and it is backed by a lot of open source projects.&lt;/p&gt;

</description>
      <category>assorted</category>
    </item>
    <item>
      <title>Good practices for presentations</title>
      <dc:creator>Bearveloper 🐻</dc:creator>
      <pubDate>Wed, 16 Dec 2020 05:00:55 +0000</pubDate>
      <link>https://dev.to/bearveloper/good-practices-for-presentations-5bmo</link>
      <guid>https://dev.to/bearveloper/good-practices-for-presentations-5bmo</guid>
      <description>&lt;p&gt;A few days ago while I was doing some note cleanup and brainstorming for post ideas, I found a list of good practices for presentations and screen sharing I wrote some years ago and, even though we are already well into the new remote age, I decided to share them with you.&lt;/p&gt;

&lt;p&gt;I hope you (or someone close to you) find them helpful.&lt;/p&gt;




&lt;h2&gt;
  
  
  Hide all system bars and desktop icons
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Objective&lt;/strong&gt; : Privacy, Avoid distractions&lt;/p&gt;

&lt;p&gt;This is a subjective one, but I can count with the fingers in my hand the times I have attended a presentation where the system bars and desktop icons were hidden, and I must say it was a big difference to avoid all these subtle distractions. How many times have you though &lt;em&gt;I use that app too!&lt;/em&gt;, &lt;em&gt;I know those icons!&lt;/em&gt;, or even worse &lt;em&gt;What program is that?&lt;/em&gt; ?.&lt;/p&gt;

&lt;p&gt;It is fairly easy to temporarily hide all this UI elements, and, the less reasons we give our audience to be distracted, the better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Move all windows to a secondary monitor
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Objective&lt;/strong&gt; : Avoid distractions, Performance&lt;/p&gt;

&lt;p&gt;Nowadays most desktop environments (Windows, macOS, different Linux flavors) support multiple virtual desktops which we can take advantage of when presenting. If for some reason you need various programs or windows open during your presentation, but you do not have to share them, use this feature to move such windows out of view.&lt;/p&gt;

&lt;p&gt;If you have the privilege of a second display this becomes even easier, just move those windows out of the shared screen while still keeping them visible to you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turn on “Do Not Disturb”
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Objective&lt;/strong&gt; : Privacy, Avoid distractions&lt;/p&gt;

&lt;p&gt;It is easy to get distracted and lose our train of though when we get notifications, alerts, popups, etc. therefore it is best to use the “Do Not Disturb” feature, not only on our mobile devices but also on our computer. Most OS today have this feature available to you in a couple of clicks, no matter where you are or what you are doing.&lt;/p&gt;

&lt;p&gt;Besides avoiding the mentioned distractions for the presenter and the audience, most notifications include text excerpts, previews or images; DND is also useful to avoid potential privacy problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quit all nonessential programs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Objective&lt;/strong&gt; : Privacy, Avoid distractions, Performance&lt;/p&gt;

&lt;p&gt;It is pretty common to keep several programs running while we are working on the computer whether they are related to our daily activities or not, like different browser tabs, email client, music, videos, reference material, etc. but most of these are not required during a presentation, hence it is better to just quit all programs that are not strictly required for the presentation. In addition to avoid distractions, it saves us from potential privacy problems and it also frees some resources to improve the computer (and internet connection) performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make use of private browsing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Objective&lt;/strong&gt; : Privacy, Avoid distractions, Performance&lt;/p&gt;

&lt;p&gt;In line with hiding system bars and desktop icons. If you are using your internet browser to present, it is recommended to use the private (incognito) browsing mode preventing this way to unintentionally sharing your browsing history, downloads, search history, etc.; as a &lt;em&gt;bonus point&lt;/em&gt;, private browsing also disables all browser extensions/plugins which will also free up some resources for the browser itself and avoid extra icons and other distractions.&lt;/p&gt;

&lt;p&gt;One more slightly advanced tip is to create an alternate browser profile for testing or presentations. This option is available in most browsers and, in my opinion it is the most flexible one, but it requires some extra fiddling and setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prepare your screen before hand
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Objective&lt;/strong&gt; : Performance, Contingency plan&lt;/p&gt;

&lt;p&gt;There is nothing like not having the right link or a sudden slow internet to throw your focus (and the rest of your presentation) out the window.&lt;/p&gt;

&lt;p&gt;Evade problems and time waste by preparing not only what you have to say, but also what you have to share; if possible, open all links on new tabs, and if you have to demo a series of interactions, open each step on a new tab or window you can use to quickly switch to if something unexpected happens.&lt;/p&gt;

&lt;p&gt;Remember Murphy’s law, &lt;em&gt;anything that can go wrong, will go wrong&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Take screenshots in a controlled environment
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Objective&lt;/strong&gt; : Performance, Contingency plan&lt;/p&gt;

&lt;p&gt;Expanding and improving the previous point, if you have the time and tools, there is nothing better than take a series of screenshots or video captures of what you will present as a contingency plan; &lt;em&gt;a picture is worth a thousand words, a video is worth a thousand pictures&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If you choose to use these images or videos on your presentation as opposed to just use them as a back plan you will be leveling up your presentation quality even more before these are taken (usually) on a controlled environment, that is, in a quiet place, with a good internet connection, ideal screen size, ideal data, etc. Some of the best technical presentations I have assisted to included one or more video captures from the presented topics.&lt;/p&gt;




&lt;p&gt;I really hope you find all these recommendations as useful for your presentations as I have along the years. You do not have to implement all of them at once, but I definitely recommend you to start using some of them and you will see immediate results.&lt;/p&gt;

</description>
      <category>tipsandtricks</category>
    </item>
    <item>
      <title>Dear new (and not so new) developers</title>
      <dc:creator>Bearveloper 🐻</dc:creator>
      <pubDate>Thu, 02 Jul 2020 00:00:22 +0000</pubDate>
      <link>https://dev.to/bearveloper/dear-new-and-not-so-new-developers-2d53</link>
      <guid>https://dev.to/bearveloper/dear-new-and-not-so-new-developers-2d53</guid>
      <description>&lt;p&gt;I understand not everyone has or will have the privileges of good mentors, internet access, or even knowing how to read and understand English, but for those who have them, is that I want to share these &lt;em&gt;bites of wisdom&lt;/em&gt; that have helped me advance my career over 17 years now.&lt;/p&gt;

&lt;p&gt;Let me give you a bit of context about me. I graduated from CS 15 years ago, in a small university at my home town (Puebla, Mexico); and paid most of it by working in a small computer repair store near my home. Most of what I know today I either learned it from great mentors I have had over the years, because of someone answering my question in some form of online platform, or self thought.&lt;/p&gt;




&lt;p&gt;When you start learning something, a programming language, a library you want to use, heck, even a new code editor, you will have that feeling of uncertainty and that is OK, do not run away from it, embrace it. If you know how to channel this feeling into questions and searches, you will go far. There is nothing more exciting and intimidating that start a new project, in an empty folder, with an empty file; so many possibilities but where and how do I start?&lt;/p&gt;

&lt;p&gt;You do not have to define a &lt;em&gt;bullet-proof, future-proof architecture&lt;/em&gt; from day 1, that is impossible. Yes, there are many companies out there with great ideas, but those ideas that worked for them will not necessarily work for you; even those big companies change direction 180º every so often, so why should you not? Just follow the Unix philosophy, take a big problem and break it in small manageable problems, solve those small problems, and eventually your big problem won’t be so big, and will be simple to solve.&lt;/p&gt;

&lt;p&gt;Do you want to build a web site from scratch? There is absolutely no need to start with Docker on day one. You don’t need Webpack to start your project. Don’t waste your time thinking if TailwindCSS or Redux are your best options. Start small, start with a plain HTML file and as you progress you will eventually find what you need and what you don’t.&lt;/p&gt;

&lt;h3&gt;
  
  
  Asking a question is hard, asking good question is even harder
&lt;/h3&gt;

&lt;p&gt;At some point you will find a blocker. Not a small one, a big one. One of those that stop your progress for hours, or even days. But there is nothing to fear about it. It is ok to not know the answer to your problem. It is ok even to not understand your problem. We are not geniuses (at least I am not) so stop thinking you have to know everything. You don’t. One of the best skills you will learn and master over the years is how to ask a good question, and not just to your friends or coworkers, but also to one of the many search engines out there.&lt;/p&gt;

&lt;p&gt;You might be tempted to just copy and paste your errors in the search engine, or dump a big chunk of code on a forum or chat window and wait for someone to magically understand it, fix it, and send it back to you. I can tell you this might work one or two times, but it will eventually wear-off and those who were willing to help you will start ignoring you. Instead, follow again the Unix philosophy, start breaking your problem in smaller ones. Remove complexities, remove unnecessary details until you end up with the bare minimum, and then give it a try one more time.&lt;/p&gt;

&lt;p&gt;Having issues fixing or adding a new style to an existing element in a webpage? Remove all styles from the element and try to get yours working. Something in your JavaScript code not working? Isolating the problem by doing something similar in a blank playground works wonders, be it a CodePen, or just a new HTML and JS file on your computer. If after isolating it you still can’t figure out what the problem is, then you have a good, clean example to ask (politely) someone else.&lt;/p&gt;

&lt;p&gt;If your problem or your question is too generic, or on the contrary, too specific, be prepared to answer some questions you will get back to you. A good way to know if you are headed on the right direction to receive help is if the person who is helping you is asking you things, context is everything! If they are just throwing random “solutions” at you, most of the time is someone who only cares about “giving an answer” first, not actually solving your problem. Our problems are many times as unique as we are, so trying to solve someone’s problem requires most times a good chunk of time and a conversation to fully understand what you need to do and why.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understand your problem, understand your solution
&lt;/h3&gt;

&lt;p&gt;In cases where you feel in a rush or specially when starting with new projects or technologies you might be tempted to ask for a how-to or tutorial, more so if you feel like you are running in circles or you are running out of time, but believe me, a tutorial or a how-to will hurt you more than it will help you. Why? Because a tutorial or a how-to is tailored to a very specific use case, with a very specific goal in mind. Stop rushing yourself and start reading more. I know, not all projects have great documentation, but it will pay forward to read the official documentation to understand what you are doing instead of just blindly following someone’s “Ho to build a To Do with X and Y” guide. Don’t get me wrong, this is not a RTFM, you do not need to read the whole thing from back to back, but at the very least take the time to read and understand the functionality you are trying to use.&lt;/p&gt;

&lt;p&gt;If you get some generic advice or links instead of a tutorial teaching you exactly what you are doing, give that person an honest &lt;strong&gt;Thank You&lt;/strong&gt; and take the time to read whatever was shared with you. That person wants you to learn by giving you the right direction instead of just spitting out the first thing that crossed their mind that may or may not work at all for you.&lt;/p&gt;

&lt;p&gt;Do not ask someone to solve your problem, ask them to explain you what you do not understand and point you in the right direction so you can solve your problem yourself.&lt;/p&gt;




&lt;p&gt;This was slightly longer than I anticipated, but believe me, I have been there more than a handful of times in my 17 years of professional experience. To summarize:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ask good questions&lt;/li&gt;
&lt;li&gt;Read the official documentation&lt;/li&gt;
&lt;li&gt;Divide your problems in smaller ones&lt;/li&gt;
&lt;li&gt;Isolate your problems to remove external actors&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>tipsandtricks</category>
    </item>
    <item>
      <title>Overlay text on images with PHP</title>
      <dc:creator>Bearveloper 🐻</dc:creator>
      <pubDate>Tue, 23 Jun 2020 04:00:06 +0000</pubDate>
      <link>https://dev.to/bearveloper/overlay-text-on-images-with-php-4ccf</link>
      <guid>https://dev.to/bearveloper/overlay-text-on-images-with-php-4ccf</guid>
      <description>&lt;p&gt;Some time ago, someone asked me how to create a list of diplomas using a static background image and a list of names. The problem was simple enough to be implemented in less than 30 mins, so I decided to give a try and here is what I ended up with.&lt;/p&gt;

&lt;p&gt;This is a simple PHP script with some assumptions that can be run directly in the command line. It can easily be tweaked to fulfill other more complex requirements, like water marking images, mobile optimized images, reading data from Google Spreadsheets or Airtable, etc., so feel free to fork the repo or download the source and hack it as you need it.&lt;/p&gt;

&lt;p&gt;With the code below I go:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;From this…&lt;/th&gt;
&lt;th&gt;…to this&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---VlXzF7P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/14p65vonnof0ccetb2i5.jpg" alt="Empty Diploma" width="880" height="680"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rshtakbk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yudnnptvvf2lfocgm5yd.jpg" alt="Filled in Diploma" width="880" height="680"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;To the code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?php

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, some variables so we can tweak the script behavior without having to figure out where in the code are this things setup&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$csv_file = 'names.csv';
$background = 'background.jpg';
$signature = 'sig.png';
$font = 'ConeriaScript.ttf';

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we read the CSV file and parse so it is easier to read later by converting it to an associative array with the column names as the keys.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// CSV code from https://www.php.net/manual/en/function.str-getcsv.php
$csv = array_map('str_getcsv', file($csv_file));
array_walk($csv, function (&amp;amp;$a) use ($csv) {
    $a = array_combine($csv[0], $a);
});
array_shift($csv);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this specific background we will need the current date as three strings to be placed in three different places.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$day = date('j');
$month = date('F');
$year = date('Y');

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we start having fun with PHP’s image functions. First, we need to read our background image to get some basic info and do some preparation, like setting the text color, the image width (for centering the text), and reading the signature image and its sizes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$image = imagecreatefromjpeg($background);
$color = imagecolorallocate($image, 0, 0, 0);
$width = imagesx($image);
$signature = imagecreatefrompng($signature);
$signature_width = imagesx($signature);
$signature_height = imagesy($signature);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have the image data ready, we will start reading each name in our list so we can generate individual images with all the overlaid text. For easier reading, I am saving the name and reason in their own variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  foreach ($csv as $row) {
    $name = $row['Name'];
    $reason = $row['Reason'];

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, I am reading the background image again. For the first item in the loop this does not make sense because I already read it above, but since all the &lt;code&gt;image*&lt;/code&gt; functions alter their input, if I do not do this I will end every image in the list will end up all the previous text from all the previous images overlapped; not good. I am also getting the text “bound boxes” which are basically the positions of the four corners of my text; I do this to be able to center the text in the image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    $image = imagecreatefromjpeg($background);
    $name_box = imagettfbbox(40, 0, $font, $name);
    $reason_box = imagettfbbox(40, 0, $font, $reason);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it is time to actually render the text on the image. This is done by providing some information to PHP, including the destination image, text size, angle, x and y position, color, font (yes you can use your fonts!), and last but not least, the actual text.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    imagettftext($image, 40, 0, ($width - $name_box[2]) / 2, 635, $color, $font, $name);
    imagettftext($image, 40, 0, ($width - $reason_box[2]) / 2, 790, $color, $font, $reason);
    imagettftext($image, 32, 0, 400, 895, $color, $font, $day);
    imagettftext($image, 32, 0, 600, 895, $color, $font, $month);
    imagettftext($image, 32, 0, 600, 975, $color, $font, $year);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the text is overlaid correctly, I need to add the “signature” image on top of the text so it looks nicer, so I tell PHP to copy the signature image (a transparent PNG file) on top, as you can see, I had to not only provide position, but also size.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    imagecopy($image, $signature, 400, 980, 0, 0, $signature_width, $signature_height);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Almost there! Here I am saving the resulting image to disk by providing a name. I I did not provide the name, PHP would just output the content, which could be used instead as a download link by also providing the correct &lt;code&gt;header&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    imagejpeg($image, "diplomas/$name.jpg");

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I do not want to clutter my memory, so once I am done with the image, it is destroyed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    imagedestroy($image);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And done, to the next item on the list!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;As you can see this is a fairly simple yet powerful script that can be used for many different purposes. Feel free to &lt;a href="https://github.com/eruizdechavez/php-diploma-generator"&gt;see or fork the full project&lt;/a&gt; and these are the links to the image functions used in this example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/function.imagecreatefromjpeg.php"&gt;imagecreatefromjpeg&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/function.imagecolorallocate.php"&gt;imagecolorallocate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/function.imagesx.php"&gt;imagesx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/function.imagesy.php"&gt;imagesy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/function.imagecreatefrompng.php"&gt;imagecreatefrompng&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/function.imagecreatefrompng.php"&gt;imagecreatefrompng&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/function.imagettfbbox.php"&gt;imagettfbbox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/function.imagettftext.php"&gt;imagettftext&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/function.imagecopy.php"&gt;imagecopy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/function.imagejpeg.php"&gt;imagejpeg&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/function.imagedestroy.php"&gt;imagedestroy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;I hope you enjoy this post and find it useful!&lt;/p&gt;

&lt;h1&gt;
  
  
  php
&lt;/h1&gt;

</description>
      <category>programming</category>
      <category>php</category>
    </item>
    <item>
      <title>Writing a Link Shortener with PHP and Airtable</title>
      <dc:creator>Bearveloper 🐻</dc:creator>
      <pubDate>Mon, 03 Feb 2020 05:00:27 +0000</pubDate>
      <link>https://dev.to/bearveloper/writing-a-link-shortener-with-php-and-airtable-38lb</link>
      <guid>https://dev.to/bearveloper/writing-a-link-shortener-with-php-and-airtable-38lb</guid>
      <description>&lt;p&gt;Over the weekend I was working on a small side project for a meetup I started attending to a few weeks ago. I am printing a QR code (with a link) for a small flyer and adding an NFC tag (with the same link) to it as well. All of the sudden I was thinking 🤔 &lt;em&gt;I need a practical way to update a my link without having to print again my QR code and reprogram the NFC tag&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;My initial thinking was to just use one of the many services out there but then I thought &lt;em&gt;why not build a really simple one so I can update it as I need?&lt;/em&gt;, I also wanted to have a quick way of updating it without having to republish the code, or jumping into an ssh session to change some file on a server.&lt;/p&gt;

&lt;p&gt;The answer 💡 I came up was to write a pretty small, yet effective, PHP script that gets an ID, fetches the real link from Airtable, and ends up redirecting the browser to the real link.&lt;/p&gt;

&lt;p&gt;To make it look fancier, I used Apache’s &lt;code&gt;mod_rewrite&lt;/code&gt; so I get a clean URL, but it is really not required.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you’ll get
&lt;/h2&gt;

&lt;p&gt;A custom URL shortener with your own domain 🎉.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you’ll need
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A server with Apache and PHP.&lt;/li&gt;
&lt;li&gt;An &lt;a href="https://airtable.com"&gt;Airtable&lt;/a&gt; account.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to put everything together
&lt;/h2&gt;

&lt;p&gt;We start by preparing Airtable. If you do not have an account, get one, it is free and really useful. Once you are ready with your account, you can &lt;a href="https://airtable.com/shrwIKP1OeFO24DYk"&gt;copy my Base&lt;/a&gt; into your account. This will save us some time and will allow you to familiarize yourself with Airtable at your own pace. The table has some fields, but the important ones are ID and URL. &lt;code&gt;ID&lt;/code&gt; is using Airtable’s record ID (removing the letters &lt;code&gt;rec&lt;/code&gt; from the beginning) and &lt;code&gt;URL&lt;/code&gt; is a string with your URL.&lt;/p&gt;

&lt;p&gt;After you are ready with your Base and Table, you need to get your Base ID and API Token. To get the Base ID go to &lt;a href="https://airtable.com/api"&gt;https://airtable.com/api&lt;/a&gt;, click on your base name and you should see an API explorer with the ID of your base in the first paragraphs of the Introduction. To get your API Token go to &lt;a href="https://airtable.com/account"&gt;https://airtable.com/account&lt;/a&gt; and you should have an obfuscated field in the API section, to get the token just click on it and it will reveal the token. I am assuming you copied my base so I’ll assume your Table name is the same as mine (if not, you can change the name on the &lt;code&gt;config.ini&lt;/code&gt; file).&lt;/p&gt;

&lt;p&gt;With this 3 pieces of information we are ready to get some magic done 🧙🏻‍♂️. We’ll start by adding a folder on our web server; since it is a link “shortener” it made sense to me to create a folder named &lt;code&gt;s&lt;/code&gt;. Inside this folder I have the following files:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.htaccess&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    RewriteEngine on

    RewriteCond %{REQUEST_FILENAME} !index.php
    RewriteRule .* index.php?id=$0 [QSA,L]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;index.php&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?php
$config = parse_ini_file('config.ini');
$id = $_GET['id'];
$request_url = 'https://api.airtable.com/v0/' . $config['base_id'] . '/' . urlencode($config['table_name']) . '/rec' . $id;

$options = [
  'http' =&amp;gt; [
    'method' =&amp;gt; 'GET',
    'header' =&amp;gt;
      'Authorization: Bearer ' . $config['token'] . "\r\n",
  ],
];
$context = stream_context_create($options);

$response = file_get_contents($request_url, false, $context);
$record = json_decode($response, true);
$url = $record['fields']['URL'];

if ($_GET['debug']) {
  echo '&amp;lt;pre&amp;gt;';
  var_dump($options);
  var_dump($response);
  var_dump($record);
  var_dump($url);
  echo '&amp;lt;/pre&amp;gt;';
} else {
  header("location: ${url}");
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;config.ini&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;base_id=your-airtable-base-id-here
table_name=Your Table Name
token=your-api-token-here

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once these 3 files are in place, there is not much else to do. We just need to have at least a link in the base, copy the ID and use it in our browser using the correct domain and path to your server. In this example, our server domain is &lt;code&gt;example.com&lt;/code&gt; and our &lt;code&gt;s&lt;/code&gt; folder is in the root of the public folder, so we could try going to &lt;code&gt;http://example.com/s/SOMEID&lt;/code&gt; (assuming also that &lt;code&gt;SOMEID&lt;/code&gt; is a valid ID in our table) and get redirected to the real URL 💥.&lt;/p&gt;

&lt;p&gt;If for some reason I need to debug 🐛 the code and see what is going on, I can add &lt;code&gt;?debug=true&lt;/code&gt; to the URL and the script will show me some variables instead of doing the redirect.&lt;/p&gt;

&lt;p&gt;There you go! A custom link shortener with very few code and you can also change the URL whenever you need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pending items
&lt;/h2&gt;

&lt;p&gt;Airtable allows you to do 5 requests per second, so you might need to use a different storage if you are thinking to go to production with this code (which I do not recommend for big or heavy usage).&lt;/p&gt;

&lt;p&gt;There is no error handling at all, nor logging, so again you need to think twice before going to production with this code 😉.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing thoughts
&lt;/h2&gt;

&lt;p&gt;I still like PHP a lot for small and quick solutions like this. I it very simple to get it up and running and I do not need to setup any monitor or daemon to keep my process running as I would need to do with Node.js.&lt;/p&gt;

&lt;p&gt;Airtable is also a very nice tool I use pretty often both from the Web UI and programatically.&lt;/p&gt;

&lt;p&gt;I hope you like and find this example useful. If so, please leave a comment and share with it with your friends 🙂.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>airtable</category>
      <category>php</category>
    </item>
  </channel>
</rss>
