<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>vedmant.com :: coding blog</title>
	<atom:link href="https://vedmant.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://vedmant.com/</link>
	<description>Sharing my personal experience in web development</description>
	<lastBuildDate>Sun, 06 Sep 2026 04:35:22 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1</generator>
	<item>
		<title>GainBook – an offline-first strength training tracker built with Expo</title>
		<link>https://vedmant.com/gainbook-offline-first-strength-training-tracker-expo/</link>
					<comments>https://vedmant.com/gainbook-offline-first-strength-training-tracker-expo/#respond</comments>
		
		<dc:creator><![CDATA[vedmant]]></dc:creator>
		<pubDate>Sun, 06 Sep 2026 04:32:43 +0000</pubDate>
				<category><![CDATA[My Projects]]></category>
		<category><![CDATA[React Native]]></category>
		<category><![CDATA[Drizzle ORM]]></category>
		<category><![CDATA[Expo]]></category>
		<category><![CDATA[Fitness]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[SQLite]]></category>
		<guid isPermaLink="false">https://vedmant.com/?p=295</guid>

					<description><![CDATA[<p>I built my own workout tracker after cycling through everything on the stores. GainBook runs entirely on your phone – no account, no cloud, no ads – on Expo SDK 57, SQLite and Drizzle. Here is what it does, and the volume model that took the longest to get right.</p>
<p>The post <a href="https://vedmant.com/gainbook-offline-first-strength-training-tracker-expo/">GainBook – an offline-first strength training tracker built with Expo</a> appeared first on <a href="https://vedmant.com">vedmant.com :: coding blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Install from <a href="https://play.google.com/store/apps/details?id=com.vedware.gainbook" target="_blank" rel="noreferrer noopener">Google Play</a>. The iOS build is currently in TestFlight, with the App Store release coming soon.</p>



<p class="wp-block-paragraph">I have been lifting for years, and over that time I went through most of the workout trackers available in the stores. Every one of them was missing something I needed: the set types I actually use, supersets that stay synchronized, training volume calculated correctly for dumbbells and single-leg exercises, or a rest timer that stays out of the way. Eventually I stopped searching and built my own.</p>



<p class="wp-block-paragraph"><strong>GainBook</strong> is a strength training tracker for iOS and Android. It runs entirely on your phone — no account, no cloud, no ads, and no internet connection required. This post is part announcement and part write-up of the parts that were actually interesting to build.</p>



<h2 class="wp-block-heading">The loop: plan, log, review</h2>



<figure class="wp-block-gallery has-nested-images columns-3 is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1183" height="2560" data-id="288" src="https://vedmant.com/wp-content/uploads/2026/09/gainbook-workout-plans-templates-scaled.jpg" alt="GainBook workout plans screen with Gym Back, Gym Legs and Gym Chest templates" class="wp-image-288" srcset="https://vedmant.com/wp-content/uploads/2026/09/gainbook-workout-plans-templates-scaled.jpg 1183w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-workout-plans-templates-139x300.jpg 139w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-workout-plans-templates-473x1024.jpg 473w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-workout-plans-templates-768x1662.jpg 768w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-workout-plans-templates-710x1536.jpg 710w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-workout-plans-templates-946x2048.jpg 946w" sizes="(max-width: 1183px) 100vw, 1183px" /></figure>



<figure class="wp-block-image size-large"><img decoding="async" width="1183" height="2560" data-id="289" src="https://vedmant.com/wp-content/uploads/2026/09/gainbook-active-workout-superset-rest-timer-scaled.jpg" alt="GainBook active workout screen showing a leg press superset and the rest timer" class="wp-image-289" srcset="https://vedmant.com/wp-content/uploads/2026/09/gainbook-active-workout-superset-rest-timer-scaled.jpg 1183w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-active-workout-superset-rest-timer-139x300.jpg 139w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-active-workout-superset-rest-timer-473x1024.jpg 473w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-active-workout-superset-rest-timer-768x1662.jpg 768w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-active-workout-superset-rest-timer-710x1536.jpg 710w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-active-workout-superset-rest-timer-946x2048.jpg 946w" sizes="(max-width: 1183px) 100vw, 1183px" /></figure>



<figure class="wp-block-image size-large"><img decoding="async" width="1183" height="2560" data-id="293" src="https://vedmant.com/wp-content/uploads/2026/09/gainbook-history-calendar-scaled.jpg" alt="GainBook history screen with a training calendar and session summaries" class="wp-image-293" srcset="https://vedmant.com/wp-content/uploads/2026/09/gainbook-history-calendar-scaled.jpg 1183w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-history-calendar-139x300.jpg 139w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-history-calendar-473x1024.jpg 473w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-history-calendar-768x1662.jpg 768w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-history-calendar-710x1536.jpg 710w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-history-calendar-946x2048.jpg 946w" sizes="(max-width: 1183px) 100vw, 1183px" /></figure>
</figure>



<p class="wp-block-paragraph">Templates are organised into plans and can be scheduled for specific weekdays. Each set has a target weight, reps, rest time and set type — warm-up, working, drop set or failure — while exercises can be grouped into supersets whose sets remain synchronised. Whether you are editing a template or standing in front of the rack, the app shows you what you did the last time you performed that exercise.</p>



<p class="wp-block-paragraph">During a workout, you log reps and weight, add or remove sets on the fly, and the rest timer starts automatically when you complete a set, with sound and a notification if you have left the app. If the equipment you need is taken, you can replace the exercise mid-session and the history records the substitution. A persistent bar on every other screen lets you jump back into an active workout.</p>



<h2 class="wp-block-heading">Volume is the part that took the longest</h2>



<p class="wp-block-paragraph">Most trackers calculate total volume as <code>sets × reps × weight</code> and leave it at that. That number is wrong in three ways that bothered me enough to fix them.</p>



<h3 class="wp-block-heading">1. Your body weight is load</h3>



<p class="wp-block-paragraph">A pull-up with no added weight is not a zero-volume set. But a plank or a glute kickback should not count the same proportion of body weight as a pull-up either. My first attempt derived the percentage from the exercise name, and the results were terrible: it assigned 60–90% to static stretches that move nothing, 70% to a single-leg kickback even though one leg is about 16% of body mass, and 70% to a hyperextension compared with 35% for a sit-up even though both rotate roughly the same mass around the same joint. The result was that three sets of hyperextensions could out-tonnage an entire bench session.</p>



<p class="wp-block-paragraph">So that heuristic is gone. Every exercise now has a reviewed body-weight load percentage, derived from <code>segment mass × lever factor</code> using Winter&#8217;s segment table (whole body 100, above the hip 68, above the knee 85, one leg 16, one arm 5), multiplied by a leverage/range-of-motion factor. The exercise name alone does not tell you how much mass a movement actually moves.</p>



<h3 class="wp-block-heading">2. A set does not train one muscle</h3>



<p class="wp-block-paragraph">A bent-over row is not simply a &#8220;back exercise&#8221; — it is roughly 42% middle back, 32% lats, with the remainder distributed across biceps, shoulders and forearms. GainBook models each exercise as a single distribution across every muscle it works, including the primary muscle, with no primary/secondary split and no cap on any individual share.</p>



<p class="wp-block-paragraph">The important part is that the set&#8217;s volume is <strong>divided</strong> across those muscles, never multiplied. The distribution always adds up to exactly 100, so the volume credited to the muscles equals the volume of the original set. All 892 exercises in the library were reviewed individually based on their own mechanics rather than inherited from a movement family, and each exercise has its own split displayed in the app.</p>



<figure class="wp-block-gallery has-nested-images columns-3 is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1183" height="2560" data-id="291" src="https://vedmant.com/wp-content/uploads/2026/09/gainbook-volume-calculation-muscle-split-scaled.jpg" alt="GainBook explaining set volume as body weight plus added weight times reps, with the pull-up muscle split" class="wp-image-291" srcset="https://vedmant.com/wp-content/uploads/2026/09/gainbook-volume-calculation-muscle-split-scaled.jpg 1183w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-volume-calculation-muscle-split-139x300.jpg 139w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-volume-calculation-muscle-split-473x1024.jpg 473w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-volume-calculation-muscle-split-768x1662.jpg 768w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-volume-calculation-muscle-split-710x1536.jpg 710w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-volume-calculation-muscle-split-946x2048.jpg 946w" sizes="auto, (max-width: 1183px) 100vw, 1183px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1183" height="2560" data-id="290" src="https://vedmant.com/wp-content/uploads/2026/09/gainbook-muscle-volume-heatmap-scaled.jpg" alt="GainBook muscle volume heatmap with quads, calves, hamstrings and glutes highlighted" class="wp-image-290" srcset="https://vedmant.com/wp-content/uploads/2026/09/gainbook-muscle-volume-heatmap-scaled.jpg 1183w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-muscle-volume-heatmap-139x300.jpg 139w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-muscle-volume-heatmap-473x1024.jpg 473w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-muscle-volume-heatmap-768x1662.jpg 768w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-muscle-volume-heatmap-710x1536.jpg 710w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-muscle-volume-heatmap-946x2048.jpg 946w" sizes="auto, (max-width: 1183px) 100vw, 1183px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1183" height="2560" data-id="292" src="https://vedmant.com/wp-content/uploads/2026/09/gainbook-muscle-volume-trend-scaled.jpg" alt="GainBook per-muscle analytics for Lats with volume, sets, sessions and a trend chart" class="wp-image-292" srcset="https://vedmant.com/wp-content/uploads/2026/09/gainbook-muscle-volume-trend-scaled.jpg 1183w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-muscle-volume-trend-139x300.jpg 139w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-muscle-volume-trend-473x1024.jpg 473w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-muscle-volume-trend-768x1662.jpg 768w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-muscle-volume-trend-710x1536.jpg 710w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-muscle-volume-trend-946x2048.jpg 946w" sizes="auto, (max-width: 1183px) 100vw, 1183px" /></figure>
</figure>



<h3 class="wp-block-heading">3. Muscle groups are not comparable at equal tonnage</h3>



<p class="wp-block-paragraph">A 98 kg bench press and a 230 kg leg press can represent roughly the same effort, so colouring a body map by raw kilograms means the legs are always on fire while the arms barely register. Each muscle group therefore has a strength capacity — how much load it can actually handle, based on intermediate 1RM standards and attributed through the app&#8217;s own distribution — and every heatmap and ranking metric is normalised against it.</p>



<p class="wp-block-paragraph">One thing I got wrong initially was normalising each muscle independently against a &#8220;hard session&#8221; reference. But a full-body workout distributes its volume across ten muscles, so no individual muscle can ever get close to that reference. A real four-exercise template peaked at 0.32, leaving the entire map inside just 27% of the colour range. The result was almost the same hazy map regardless of what you trained. The map was effectively answering &#8220;how does this compare to a maximal session?&#8221; when the useful question is &#8220;where did this workout&#8217;s work go?&#8221;. Now the whole map is resolved together: the shape is stretched so the hardest-worked muscle reaches the top of the range, then dimmed according to the overall magnitude of the session. That way, a warm-up still cannot look like a leg day.</p>



<p class="wp-block-paragraph">Warm-up sets, incidentally, do not count toward training volume at all. A 25-rep bar-only warm-up used to light up the heatmap just like a working set.</p>



<h2 class="wp-block-heading">Everything stays on the device</h2>



<p class="wp-block-paragraph">There is no backend. The entire app is a local SQLite database (<code>expo-sqlite</code>) accessed through <a href="https://orm.drizzle.team/" target="_blank" rel="noreferrer noopener">Drizzle ORM</a>, with schema migrations generated from the TypeScript schema. No account, no sync, no server bill, and nothing to leak.</p>



<p class="wp-block-paragraph">The trade-off is that backups are entirely my problem, so there are three options and they all produce <strong>the same file</strong>: the share-sheet export you can send to yourself, automatic iCloud Drive backup on iOS, and Android Auto Backup. A backup taken from the Files app is byte-identical to an export, so it can always be imported again. Creating a separate private backup format would have meant that the user&#8217;s own copy might no longer be restorable.</p>



<p class="wp-block-paragraph">That file is a zip containing a single <code>gainbook.db</code>. A workout log consists of short, repetitive rows spread across mostly-empty SQLite pages, so it compresses by roughly 8×: a synthetic three-year history of 450 sessions and 10,800 sets went from 672 KB down to 83 KB. Import detects the file from its <em>leading bytes</em> rather than relying on the extension or MIME type, because a file that has passed through a share sheet or two may arrive with whatever filename the last app decided to give it. It also still accepts the uncompressed databases exported before the zip change, since those files are already sitting in people&#8217;s Files apps and there is no migration mechanism that can reach them.</p>



<h2 class="wp-block-heading">The exercise library</h2>


<div class="wp-block-image">
<figure class="aligncenter size-large is-resized"><img loading="lazy" decoding="async" width="1183" height="2560" src="https://vedmant.com/wp-content/uploads/2026/09/gainbook-exercise-library-detail-scaled.jpg" alt="GainBook exercise detail for Dumbbell Bench Press with photo, muscle groups and equipment tags" class="wp-image-294" style="width:340px;height:auto" srcset="https://vedmant.com/wp-content/uploads/2026/09/gainbook-exercise-library-detail-scaled.jpg 1183w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-exercise-library-detail-139x300.jpg 139w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-exercise-library-detail-473x1024.jpg 473w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-exercise-library-detail-768x1662.jpg 768w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-exercise-library-detail-710x1536.jpg 710w, https://vedmant.com/wp-content/uploads/2026/09/gainbook-exercise-library-detail-946x2048.jpg 946w" sizes="auto, (max-width: 1183px) 100vw, 1183px" /><figcaption class="wp-element-caption">Exercise detail, including the 2× volume multiplier for dumbbell work.</figcaption></figure>
</div>


<p class="wp-block-paragraph">The bundled library is based on <a href="https://github.com/yuhonas/free-exercise-db" target="_blank" rel="noreferrer noopener">free-exercise-db</a> (public domain) — 892 exercises with instructions, photos, equipment and difficulty — combined with the muscle distribution and body-weight load data described above. You can search by name, muscle group or equipment, add your own exercises, and open any exercise to see its complete history and per-muscle trend. Custom exercises can only be deleted when nothing still references them.</p>



<h2 class="wp-block-heading">Stack</h2>



<ul class="wp-block-list">
<li><a href="https://docs.expo.dev/" target="_blank" rel="noreferrer noopener">Expo SDK 57</a> / React Native 0.86, New Architecture enabled</li>



<li><a href="https://docs.expo.dev/router/introduction/" target="_blank" rel="noreferrer noopener">Expo Router</a> for file-based navigation</li>



<li><code>expo-sqlite</code> + <a href="https://orm.drizzle.team/" target="_blank" rel="noreferrer noopener">Drizzle ORM</a> for local storage and migrations</li>



<li>Reanimated and FlashList for the set-logging screens</li>



<li>HealthKit on iOS — workouts written to Apple Health, live heart rate from Apple Watch or AirPods, per-set max heart rate and active energy</li>



<li>A vendored picker and three small native modules (iCloud backup, Live Activities)</li>



<li><a href="https://maestro.mobile.dev/" target="_blank" rel="noreferrer noopener">Maestro</a> for end-to-end tests on both simulators, plus Jest for the model code</li>



<li>English, Spanish and Russian</li>



<li>OTA updates through <code>expo-updates</code> on fingerprint runtime versions</li>
</ul>



<p class="wp-block-paragraph">That last one probably deserves its own post. With <code>runtimeVersion.policy</code> set to <code>fingerprint</code>, the hash <em>is</em> the runtime version, and anything that changes it can silently strand every binary already in the field. Nothing errors; the update simply never gets offered. In my case, an ESLint-only commit generated a new runtime version because <code>package.json</code> scripts were included in the hash. It is worth knowing about before you ship one.</p>



<h2 class="wp-block-heading">Try it</h2>



<p class="wp-block-paragraph">GainBook is free on <a href="https://play.google.com/store/apps/details?id=com.vedware.gainbook" target="_blank" rel="noreferrer noopener">Google Play</a>, with iOS following shortly. I train with it every week, which is the main reason it keeps evolving — whenever I find something missing, I build it. If you prefer owning your training data instead of storing it on someone else&#8217;s server, that is exactly what GainBook is built for.</p>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://vedmant.com/gainbook-offline-first-strength-training-tracker-expo/">GainBook – an offline-first strength training tracker built with Expo</a> appeared first on <a href="https://vedmant.com">vedmant.com :: coding blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://vedmant.com/gainbook-offline-first-strength-training-tracker-expo/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Running Time &#8211; React Native Sample Application</title>
		<link>https://vedmant.com/running-time-react-native-sample-application/</link>
					<comments>https://vedmant.com/running-time-react-native-sample-application/#comments</comments>
		
		<dc:creator><![CDATA[vedmant]]></dc:creator>
		<pubDate>Sun, 24 Nov 2019 19:23:02 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[My Projects]]></category>
		<category><![CDATA[React Native]]></category>
		<category><![CDATA[Mobile App]]></category>
		<guid isPermaLink="false">https://vedmant.com/?p=276</guid>

					<description><![CDATA[<p>Open sources GitHub. Install App from Play Market. Not so long ago I created a simple running tracker &#8211; Running Time that was build on Laravel and Vue as a tutorial to build Single Page Applications. It turned out to be quite helpful learning app for many people. Now I decided to get to know &#8230; <a href="https://vedmant.com/running-time-react-native-sample-application/" class="more-link">Continue reading <span class="screen-reader-text">Running Time &#8211; React Native Sample Application</span></a></p>
<p>The post <a href="https://vedmant.com/running-time-react-native-sample-application/">Running Time &#8211; React Native Sample Application</a> appeared first on <a href="https://vedmant.com">vedmant.com :: coding blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Open sources <a href="https://github.com/vedmant/running-time-react" target="_blank" rel="noreferrer noopener" aria-label=" (opens in a new tab)">GitHub</a>. Install App from <a href="https://play.google.com/store/apps/details?id=com.vedmant.runningtime" target="_blank" rel="noreferrer noopener" aria-label=" (opens in a new tab)">Play Market</a>.</p>



<p class="wp-block-paragraph">Not so long ago I created a simple running tracker &#8211; <a href="https://github.com/vedmant/running-time">Running Time</a> that was build on Laravel and Vue as a tutorial to build Single Page Applications. It turned out to be quite helpful learning app for many people. Now I decided to get to know React Native a bit more and in the process I created an app that uses that same Laravel API backend.</p>



<p class="wp-block-paragraph">This mobile App is quite simple it has authentication flow with register and login pages. Main screen with three tabs, &#8220;Dashboard&#8221;, &#8220;Entries&#8221; and &#8220;Profile&#8221;. </p>



<p class="wp-block-paragraph">Here is more detailed list of features:</p>



<ul class="wp-block-list"><li>Simple and clean code</li><li>Redux with redux-thunk</li><li>Auth flow: login and registration</li><li>Dashboard tab with panels and charts</li><li>Entries list tab</li><li>Add / edit entry</li><li>Infinite scroll</li><li>Pull to refresh</li><li>Profile tab: update profile</li></ul>



<p class="wp-block-paragraph">The app is free to use and modify in any way and has MIT license.</p>



<p class="wp-block-paragraph">Open sources <a rel="noreferrer noopener" href="https://github.com/vedmant/running-time-react" target="_blank">GitHub</a>. Install App from <a rel="noreferrer noopener" href="https://play.google.com/store/apps/details?id=com.vedmant.runningtime" target="_blank">Play Market</a>.</p>
<p>The post <a href="https://vedmant.com/running-time-react-native-sample-application/">Running Time &#8211; React Native Sample Application</a> appeared first on <a href="https://vedmant.com">vedmant.com :: coding blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://vedmant.com/running-time-react-native-sample-application/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Laravel Shortcodes</title>
		<link>https://vedmant.com/laravel-shortcodes/</link>
					<comments>https://vedmant.com/laravel-shortcodes/#comments</comments>
		
		<dc:creator><![CDATA[vedmant]]></dc:creator>
		<pubDate>Tue, 23 Apr 2019 13:41:41 +0000</pubDate>
				<category><![CDATA[Laravel]]></category>
		<category><![CDATA[My Projects]]></category>
		<category><![CDATA[Composer]]></category>
		<category><![CDATA[Package]]></category>
		<category><![CDATA[Shortcodes]]></category>
		<category><![CDATA[Wordpress]]></category>
		<guid isPermaLink="false">https://vedmant.com/?p=241</guid>

					<description><![CDATA[<p>WordPress based Shortcodes for Laravel 5.x with shared variables, debugbar integration, flexible configuration and other useful features. Github: https://github.com/vedmant/laravel-shortcodes﻿ Build powerful and simple layouts using shortcodes in the content or views like this: Installation Via Composer This package supports Laravel Auto-Discover and will be discovered automatically. For Laravel version before 5.5 please add the Vedmant\LaravelShortcodes\LaravelShortcodesServiceProvider::class &#8230; <a href="https://vedmant.com/laravel-shortcodes/" class="more-link">Continue reading <span class="screen-reader-text">Laravel Shortcodes</span></a></p>
<p>The post <a href="https://vedmant.com/laravel-shortcodes/">Laravel Shortcodes</a> appeared first on <a href="https://vedmant.com">vedmant.com :: coding blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">WordPress based Shortcodes for Laravel 5.x with shared variables, debugbar integration, flexible configuration and other useful features.</p>



<p class="wp-block-paragraph">Github: <a href="https://github.com/vedmant/laravel-shortcodes" target="_blank" rel="noreferrer noopener" aria-label=" (opens in a new tab)">https://github.com/vedmant/laravel-shortcodes﻿</a></p>



<p class="wp-block-paragraph">Build powerful and simple layouts using shortcodes in the content or views like this:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: xml; title: ; notranslate">
&#x5B;b]Bold text&#x5B;/b]
&#x5B;row]
  &#x5B;col md=8]
     &#x5B;posts_list types="post,gallery" show_tags="yes"]
  &#x5B;/col]
  &#x5B;col md=4]
     &#x5B;poll id="1"]
     &#x5B;user_info username="test_user" website="mywebsite.com" active="yes"]
     &#x5B;last_free_post title="Free Posts"]
  &#x5B;/col]
&#x5B;/row]
</pre></div>


<h2 class="wp-block-heading"><a href="https://github.com/vedmant/laravel-shortcodes#installation"></a>Installation</h2>



<p class="wp-block-paragraph">Via Composer</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
$ composer require vedmant/laravel-shortcodes
</pre></div>


<p class="wp-block-paragraph">This package supports Laravel Auto-Discover and will be discovered automatically.</p>



<p class="wp-block-paragraph">For Laravel version before 5.5 please add the Vedmant\LaravelShortcodes\LaravelShortcodesServiceProvider::class to the providers array in&nbsp;<code>config/app.php</code>. And optionally &#8216;Shortcodes&#8217; =&gt; Vedmant\LaravelShortcodes\Facades\Shortcodes::class, to aliases.</p>



<h2 class="wp-block-heading"><a href="https://github.com/vedmant/laravel-shortcodes#configuraton"></a>Configuraton</h2>



<p class="wp-block-paragraph">Publish configuration.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
php artisan vendor:publish --tag=shortcodes
</pre></div>


<h2 class="wp-block-heading"><a href="https://github.com/vedmant/laravel-shortcodes#usage"></a>Usage</h2>



<h3 class="wp-block-heading"><a href="https://github.com/vedmant/laravel-shortcodes#shortcode-class"></a>Shortcode class</h3>



<p class="wp-block-paragraph">Shortcode class should extend abstract \Vedmant\LaravelShortcodes\Shortcode class.</p>



<p class="wp-block-paragraph">This packages adds&nbsp;<code>make:shortcode</code>&nbsp;artisan command:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
php artisan make:shortcode PostsListShortcode
</pre></div>


<p class="wp-block-paragraph">It will generate a shortcode class in the&nbsp;<code>app/Shortcodes</code>&nbsp;folder by default.</p>



<h3 class="wp-block-heading"><a href="https://github.com/vedmant/laravel-shortcodes#register-shortcodes"></a>Register shortcodes</h3>



<p class="wp-block-paragraph">You can use AppServiceProvider boot method to register all needed shortcodes.</p>



<p class="wp-block-paragraph">Using shortcode class:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
Shortcodes::add('b', BShortcode::class);
</pre></div>


<p class="wp-block-paragraph">Using shortcode classes in array, preferable for lots of shortcodes:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
Shortcodes::add(&#x5B;
   &#039;a&#039; =&gt; AShortcode::class,
   &#039;b&#039; =&gt; BShortcode::class,
]);
</pre></div>


<p class="wp-block-paragraph">Using closure:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
Shortcodes::add(&#039;test&#039;, function ($atts, $content, $tag, $manager) {
   return new HtmlString(&#039;&lt;strong&gt;some test shortcode&lt;/strong&gt;&#039;);
});

</pre></div>


<h3 class="wp-block-heading"><a href="https://github.com/vedmant/laravel-shortcodes#rendering-shortcodes"></a>Rendering shortcodes</h3>



<p class="wp-block-paragraph">By default this packages extends View to parse all shortcodes during views rendering. This feature can be disabled in the config file.</p>



<p class="wp-block-paragraph">Also to enable / disable rendering shortcodes for specific view you can use:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
view(&#039;some-view&#039;)-&gt;withShortcodes(); // Or view(&#039;some-view&#039;)-&gt;withoutShortcodes();
</pre></div>


<p class="wp-block-paragraph">To render shortcodes manually use:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
{{ Shortcodes::render('&#x5B;b]bold&#x5B;/b]') }}
</pre></div>


<h3 class="wp-block-heading"><a href="https://github.com/vedmant/laravel-shortcodes#shared-attributes"></a>Shared attributes</h3>



<p class="wp-block-paragraph">YOccasionally, you may need to share a piece of data with all shortcodes that are rendered by your application. You may do so using the shortode facade&#8217;s&nbsp;<code>share</code>&nbsp;method. Typically, you should place calls to share in the controller, or within a service provider&#8217;s boot method.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
Shortcodes::share('post', $post);
</pre></div>


<p class="wp-block-paragraph">Then you can get share attributes in the shortcode class:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
$post = $this-&gt;shared(&#039;post&#039;); $allShared = $this-&gt;shared();
</pre></div>


<h3 class="wp-block-heading"><a href="https://github.com/vedmant/laravel-shortcodes#comma-separated-values-array-attributes"></a>Comma separated values (array attributes)</h3>



<p class="wp-block-paragraph">If you need to pass an array to a shortcode, you can pass values separated by comma:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
&#x5B;posts_list ids="1,2,3"]
</pre></div>


<p class="wp-block-paragraph">Then in render function you can parse this attribute using build in method:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
$ids = $this-&gt;parseCommaSeparated($atts&#x5B;&#039;ids&#039;]);
</pre></div>


<p class="wp-block-paragraph">Edit configuration file as needed.</p>



<h3 class="wp-block-heading"><a href="https://github.com/vedmant/laravel-shortcodes#integration-with-laravel-debugbar"></a>Integration with Laravel Debugbar</h3>



<p class="wp-block-paragraph">This packages supports Laravel Debugbar. Integration can be disabled in the config file if needed.<br></p>



<p class="wp-block-paragraph">This project is fully free to use for any purpose and licensed under MIT License.</p>
<p>The post <a href="https://vedmant.com/laravel-shortcodes/">Laravel Shortcodes</a> appeared first on <a href="https://vedmant.com">vedmant.com :: coding blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://vedmant.com/laravel-shortcodes/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>My Little Bitcoin &#8211; simple cryptocurrency implementation on JavaScript with GUI</title>
		<link>https://vedmant.com/little-bitcoin-simple-cryptocurrency-implementation-javascript-gui/</link>
					<comments>https://vedmant.com/little-bitcoin-simple-cryptocurrency-implementation-javascript-gui/#comments</comments>
		
		<dc:creator><![CDATA[vedmant]]></dc:creator>
		<pubDate>Sun, 01 Oct 2017 20:14:25 +0000</pubDate>
				<category><![CDATA[Cryptocurrency]]></category>
		<category><![CDATA[My Projects]]></category>
		<category><![CDATA[Node.js]]></category>
		<category><![CDATA[Vue.js]]></category>
		<category><![CDATA[vue-router]]></category>
		<category><![CDATA[Vuex]]></category>
		<category><![CDATA[Web Sockets]]></category>
		<guid isPermaLink="false">https://vedmant.com/?p=209</guid>

					<description><![CDATA[<p>I was interested in Bitcoin and Blockchain technologies for a while and in theory things look pretty simple yet so powerful. I really admire genius of Satoshi Nakamoto or whoever invented Blockchain based Crypto Currency and eventually I decided to implement my own simple cryptocurrency to study it better, as for me the best way &#8230; <a href="https://vedmant.com/little-bitcoin-simple-cryptocurrency-implementation-javascript-gui/" class="more-link">Continue reading <span class="screen-reader-text">My Little Bitcoin &#8211; simple cryptocurrency implementation on JavaScript with GUI</span></a></p>
<p>The post <a href="https://vedmant.com/little-bitcoin-simple-cryptocurrency-implementation-javascript-gui/">My Little Bitcoin &#8211; simple cryptocurrency implementation on JavaScript with GUI</a> appeared first on <a href="https://vedmant.com">vedmant.com :: coding blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">I was interested in Bitcoin and Blockchain technologies for a while and in theory things look pretty simple yet so powerful. I really admire genius of Satoshi Nakamoto or whoever invented Blockchain based Crypto Currency and eventually I decided to implement my own simple cryptocurrency to study it better, as for me the best way to learn is to do it myself.</p>



<p class="wp-block-paragraph">And the result is <strong>My Little Bitcoin</strong> &#8211; a simple cryptocurrency implementation on JavaScript in just about 650 lines of code (without comments and client). It also includes WEB GUI written on Vue.js where you can send coins and explore blockchain.</p>



<h3 class="wp-block-heading">The structure</h3>



<p class="wp-block-paragraph">The project is based on Node.js and has following basic structure:</p>



<ol class="wp-block-list"><li>Library &#8211; consist of functions to help handle crypto currency in a simplest way</li><li>Store &#8211; this in-memory storage for blockchain, wallets, mempool and few other things</li><li>Miner &#8211; this a worker that adds new blocks to the chain</li><li>Peers &#8211; simple peer-to-peer blockchain synchronization implementation</li><li>Server &#8211; web server that serves data for our front end GUI, includes API and web sockets</li></ol>



<h3 class="wp-block-heading">The chain</h3>



<p class="wp-block-paragraph">The structure of the chain is the simplest possible.</p>



<p class="wp-block-paragraph">Block structure is following:</p>


<pre class="brush: jscript; title: ; notranslate">
{
  index, // Block index
  prevHash, // Hash of the previous block
  time, // Current block timestamp
  transactions, // List of transactions, included into the block
  nonce, // Nonce, required for proof of work protocol
  hash, // Current block hash
}
</pre>



<p class="wp-block-paragraph">Transaction structure is following:</p>


<pre class="brush: jscript; title: ; notranslate">
{
  id, // Transaction unique id
  time, // Transaction timestamp
  hash, // Transaction hash
  reward, // Boolean to mark mining reward transaction
  inputs, // List of inputs in the transaction
  outputs, // List of outputs in transaction
  address, // Transaction is limited to only one input address for simplicity
  hash, // Transaction hash
  signature, // Transaction hash signature
}
</pre>



<p class="wp-block-paragraph">And following inputs and outputs structure:</p>


<pre class="brush: jscript; title: ; notranslate">
// Input
{
  tx, // Points to transaction of referenced output
  index, // Index of the output in the referenced transaction
  amount, // Amount of the referenced output
  address, // Address of the referenced output and also public key
  signature, // Signature, signed by private key and can be verified by included public key
}
// Output
{
  index, // Output index in current transaction
  amount, // Amount of the output
  address, // Address of the wallet (public key)
}
</pre>



<p class="wp-block-paragraph">For demo purpose I created special mode that disables peer-to-peer module, reduces proof of work difficulty and adds one minute block timeout.</p>


<div class="carousel-slider-outer carousel-slider-outer-image-carousel carousel-slider-outer-217" style="--carousel-slider-nav-color:#f1f1f1;--carousel-slider-active-nav-color:#4caf50;--carousel-slider-arrow-size:48px;--carousel-slider-bullet-size:10px">
<div id="&#039;id-217" class="carousel-slider carousel-slider-217 arrows-visibility-always dots-visibility-never arrows-outside dots-center dots-circle owl-carousel" data-slide-type="image-carousel" data-owl-settings='{"nav":true,"dots":false,"slideBy":1,"stagePadding":0,"margin":10,"loop":true,"lazyLoad":true,"autoplay":true,"autoplayTimeout":5000,"autoplaySpeed":500,"autoplayHoverPause":false,"autoWidth":false,"responsive":{"300":{"items":1},"576":{"items":1},"768":{"items":1},"1024":{"items":1},"1280":{"items":1},"1536":{"items":1}}}'>
<div class="carousel-slider__item">
	<img class="owl-lazy" data-src="https://vedmant.com/wp-content/uploads/2017/10/1.jpg" alt=""></a></div>

<div class="carousel-slider__item">
	<img class="owl-lazy" data-src="https://vedmant.com/wp-content/uploads/2017/10/2.jpg" alt=""></a></div>

<div class="carousel-slider__item">
	<img class="owl-lazy" data-src="https://vedmant.com/wp-content/uploads/2017/10/3.jpg" alt=""></a></div>

</div><!-- .carousel-slider-217 -->
</div><!-- .carousel-slider-outer-217 -->




<p class="wp-block-paragraph"><a href="https://my-little-bitcoin.vedmant.com/" target="_blank" rel="noopener">Demo</a></p>



<p class="wp-block-paragraph">Check sources here: <a href="https://github.com/vedmant/my-little-bitcoin" target="_blank" rel="noopener">GitHub Link</a></p>



<p class="wp-block-paragraph">This implementation is pretty naive and suitable only for studying purpose.</p>



<p class="wp-block-paragraph">This project is fully free to use for any purpose and licensed under MIT License.</p>
<p>The post <a href="https://vedmant.com/little-bitcoin-simple-cryptocurrency-implementation-javascript-gui/">My Little Bitcoin &#8211; simple cryptocurrency implementation on JavaScript with GUI</a> appeared first on <a href="https://vedmant.com">vedmant.com :: coding blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://vedmant.com/little-bitcoin-simple-cryptocurrency-implementation-javascript-gui/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title>How to setup Node.js production application on Apache multiple virtual host server</title>
		<link>https://vedmant.com/setup-node-js-production-application-apache-multiple-virtual-host-server/</link>
					<comments>https://vedmant.com/setup-node-js-production-application-apache-multiple-virtual-host-server/#comments</comments>
		
		<dc:creator><![CDATA[vedmant]]></dc:creator>
		<pubDate>Thu, 28 Sep 2017 12:47:53 +0000</pubDate>
				<category><![CDATA[Node.js]]></category>
		<category><![CDATA[Servers]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Reverse Proxy]]></category>
		<category><![CDATA[Web Sockets]]></category>
		<guid isPermaLink="false">https://vedmant.com/?p=201</guid>

					<description><![CDATA[<p>When it comes to using Node.js on backend it&#8217;s quite different from what people used to do for PHP server configuration. Process manager First and most important is not to run your application directly with node app.js command instead use one of the following packages: forever, PM2, and some others. This will help maintain your &#8230; <a href="https://vedmant.com/setup-node-js-production-application-apache-multiple-virtual-host-server/" class="more-link">Continue reading <span class="screen-reader-text">How to setup Node.js production application on Apache multiple virtual host server</span></a></p>
<p>The post <a href="https://vedmant.com/setup-node-js-production-application-apache-multiple-virtual-host-server/">How to setup Node.js production application on Apache multiple virtual host server</a> appeared first on <a href="https://vedmant.com">vedmant.com :: coding blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>When it comes to using Node.js on backend it&#8217;s quite different from what people used to do for PHP server configuration.</p>
<h3>Process manager</h3>
<p>First and most important is not to run your application directly with <code>node app.js</code> command instead use one of the following packages: <a href="https://github.com/foreverjs/forever" rel="noopener" target="_blank">forever</a>, <a href="https://github.com/Unitech/pm2" rel="noopener" target="_blank">PM2</a>, and some others. This will help maintain your Node application process and restart it if it crashes.</p>
<p>My own pick is PM2 as it&#8217;s the most popular and has lots of features, great app monitoring, easy installations and usage.</p>
<p>Installation is quite simple, just using npm or yarn package managers. You probably will install it globally under root user so it can be accessible for all server users.</p>
<pre class="brush: plain; title: ; notranslate">
&#x5B;root@theserver ~]$ npm -g install pm2 
# Or
&#x5B;root@theserver ~]$ yarn global add pm2 
</pre>
<p>Then switch to the user, your virtual host will be using, let&#8217;s call it <code>theproject</code>, and run pm2 startup</p>
<pre class="brush: plain; title: ; notranslate">
&#x5B;theproject@theserver ~]$ pm2 startup
</pre>
<p>It will respond with a message like this:<br />
[PM2] Init System found: systemd<br />
[PM2] To setup the Startup Script, copy/paste the following command: <the command here>
<p>It will require to run command with root privileges, using sudo user or root user directly:</p>
<pre class="brush: plain; title: ; notranslate">
&#x5B;root@theserver ~]$ &lt;the command from pm2 startup here&gt;
</pre>
<p>If everything is successful it will add a PM2 service that will run on the system boot under your user <code>theproject</code>. It&#8217;s not recommended to install pm2 <code>pm2 startup</code> under the root user directly as it will run all your application scripts under root user as well.</p>
<p>Then you will need to add PM2 process configuration file, it supports json, js, yaml formats, here is the simplest example, <code>process.yaml</code> file:</p>
<pre class="brush: plain; title: ; notranslate">
apps:
  - name: theproject
    script: app.js
    exec_mode: fork
</pre>
<p>Check more info about process file <a href="http://pm2.keymetrics.io/docs/usage/application-declaration/" rel="noopener" target="_blank">here</a>.</p>
<p>To run your application, <code>cd</code> to your project folder, and run <code>pm2 start process.yml</code></p>
<pre class="brush: plain; title: ; notranslate">
&#x5B;theproject@theserver ~]$ cd theproject
&#x5B;theproject@theserver theproject]$ pm2 start process.yml
</pre>
<p>It will start your application and print current status table.</p>
<p>To make sure your app will start again after server restart, run:</p>
<pre class="brush: plain; title: ; notranslate">
&#x5B;theproject@theserver theproject]$ pm2 save
</pre>
<p>You can nicely monitor your app using command <code>pm2 monit</code>, check current list of apps <code>pm2 list</code> and view last log records <code>pm2 logs</code>. To get further insights into your app, go to <a href="https://keymetrics.io/" rel="noopener" target="_blank">https://keymetrics.io/</a> setup account and follow instructions, the functionality is really awesome and must have for any production project.</p>
<h3>Apache configuration</h3>
<p>When our app is up and running on server we actually need to access it somehow using our domain name and 80 port, yet our app is running on some port like 3000 and is available only on 127.0.0.1 (localhost) ip (if not, it might be a security issue).</p>
<p>On 80 port we already have Apache running, so we can use Apache as a reverse proxy for our application. For you you will need to make sure Apache has <code>mod_proxy</code> installed and enabled.</p>
<p>Apache Virtual host configuration will be following:</p>
<pre class="brush: plain; title: ; notranslate">
&lt;VirtualHost *:80&gt;
  ServerName theproject.com
  ServerAlias www.theproject.com
  ErrorLog /home/theproject/logs/error_log
  CustomLog /home/theproject/logs/access_log combined

  ProxyRequests Off
  ProxyPreserveHost On

  ProxyPass / http://localhost:3000/
  ProxyPassReverse / http://localhost:3000/

  # This is needed only if you want to use web sockets
  RewriteEngine On
  RewriteCond %{REQUEST_URI}  ^/socket.io            &#x5B;NC]
  RewriteCond %{QUERY_STRING} transport=websocket    &#x5B;NC]
  RewriteRule /(.*)           ws://localhost:3000/$1 &#x5B;P,L]
&lt;/VirtualHost&gt;
</pre>
<p>After restarting Apache you should be able to successfully access your app using your domain address http://theproject.com.</p>
<p>This configuration also supports socket.io in case you may use web sockets with your application, which is very common with Node apps.</p>
<p>The post <a href="https://vedmant.com/setup-node-js-production-application-apache-multiple-virtual-host-server/">How to setup Node.js production application on Apache multiple virtual host server</a> appeared first on <a href="https://vedmant.com">vedmant.com :: coding blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://vedmant.com/setup-node-js-production-application-apache-multiple-virtual-host-server/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>Sample Single Page Application (SPA) using Laravel 5 &#038; Vue2 + Vuex + Vue-Router</title>
		<link>https://vedmant.com/sample-single-page-application-spa-using-laravel-5-vue2-vuex-vue-router/</link>
					<comments>https://vedmant.com/sample-single-page-application-spa-using-laravel-5-vue2-vuex-vue-router/#comments</comments>
		
		<dc:creator><![CDATA[vedmant]]></dc:creator>
		<pubDate>Sat, 19 Aug 2017 18:04:16 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[My Projects]]></category>
		<category><![CDATA[Vue.js]]></category>
		<category><![CDATA[E2E tests]]></category>
		<category><![CDATA[phpunit]]></category>
		<category><![CDATA[REST API]]></category>
		<category><![CDATA[SPA]]></category>
		<category><![CDATA[vue-router]]></category>
		<category><![CDATA[Vuex]]></category>
		<guid isPermaLink="false">https://vedmant.com/?p=180</guid>

					<description><![CDATA[<p>Not to long ago I implemented a sample Single Page Application using Laravel 5 and Vue2 + Vuex + Vue-Router. Today I decided to make it public and share my experience with others. The project is basically a simple Running Tracker, where you can add your running entries and see your performance during some period &#8230; <a href="https://vedmant.com/sample-single-page-application-spa-using-laravel-5-vue2-vuex-vue-router/" class="more-link">Continue reading <span class="screen-reader-text">Sample Single Page Application (SPA) using Laravel 5 &#038; Vue2 + Vuex + Vue-Router</span></a></p>
<p>The post <a href="https://vedmant.com/sample-single-page-application-spa-using-laravel-5-vue2-vuex-vue-router/">Sample Single Page Application (SPA) using Laravel 5 &#038; Vue2 + Vuex + Vue-Router</a> appeared first on <a href="https://vedmant.com">vedmant.com :: coding blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Not to long ago I implemented a sample Single Page Application using Laravel 5 and Vue2 + Vuex + Vue-Router.</p>
<p>Today I decided to make it public and share my experience with others.</p>
<p>The project is basically a simple Running Tracker, where you can add your running entries and see your performance during some period of time.</p>
<h3>Main features</h3>
<ul>
<li>Fully separate Backend and Frontend</li>
<li>Authentication based on Laravel Passport</li>
<li>List pages with filters and CRUD editing</li>
<li>Admin panel</li>
<li>Simple widgets</li>
<li>Simple reports</li>
<li>Full Phpunit test coverage</li>
<li>Sample E2E tests using Nightwatch and Cypress</li>
</ul>
<h3>Includes</h3>
<ul>
<li><a href="https://laravel.com/docs/5.4/passport">Laravel Passport</a> API Authentication</li>
<li><a href="https://github.com/mpociot/laravel-apidoc-generator">API Docs Gerator</a> Laravel API Documentation Generator</li>
<li><a href="https://github.com/barryvdh/laravel-debugbar">Laravel DebugBar</a> Debug bar for Laravel</li>
<li><a href="https://vuejs.org/">Vue.js</a> The Progressive JavaScript Framework</li>
<li><a href="https://vuex.vuejs.org/en/intro.html">Vuex</a> State management pattern + library for Vue.js</li>
<li><a href="https://router.vuejs.org/en/">Vue-Router</a> Router library for Vue.js</li>
</ul>
<h3>Other Features</h3>
<ul>
<li>Front page</li>
<li>Authentication (registration, login, logout, throttle)</li>
<li>Users roles: administrator (all access), manager (manage records)</li>
<li>User dashborad with widgets and charts</li>
<li>Entries list with filter by date (list, show, edit, delete, create)</li>
<li>Report page with chart</li>
<li>User profile page</li>
<li>Admin dashboard with widgets</li>
<li>Users admin (list, show, edit, delete, create)</li>
<li>Entries admin (list, show, edit, delete, create)</li>
<li>Global loader for all requests with small delay</li>
</ul>
<p><div class="carousel-slider-outer carousel-slider-outer-image-carousel carousel-slider-outer-191" style="--carousel-slider-nav-color:#f1f1f1;--carousel-slider-active-nav-color:#4caf50;--carousel-slider-arrow-size:48px;--carousel-slider-bullet-size:10px">
<div id="&#039;id-191" class="carousel-slider carousel-slider-191 arrows-visibility-always dots-visibility-never arrows-outside dots-center dots-circle owl-carousel" data-slide-type="image-carousel" data-owl-settings='{"nav":true,"dots":false,"slideBy":1,"stagePadding":0,"margin":10,"loop":true,"lazyLoad":true,"autoplay":true,"autoplayTimeout":10000,"autoplaySpeed":500,"autoplayHoverPause":true,"autoWidth":false,"responsive":{"300":{"items":1},"576":{"items":1},"768":{"items":1},"1024":{"items":1},"1280":{"items":1},"1536":{"items":1}}}'>
<div class="carousel-slider__item">
	<img class="owl-lazy" data-src="https://vedmant.com/wp-content/uploads/2017/08/2017-08-19_1712.jpg" alt=""></a></div>

<div class="carousel-slider__item">
	<img class="owl-lazy" data-src="https://vedmant.com/wp-content/uploads/2017/08/2017-08-19_1713.jpg" alt=""></a></div>

<div class="carousel-slider__item">
	<img class="owl-lazy" data-src="https://vedmant.com/wp-content/uploads/2017/08/2017-08-19_1713.png" alt=""></a></div>

<div class="carousel-slider__item">
	<img class="owl-lazy" data-src="https://vedmant.com/wp-content/uploads/2017/08/2017-08-19_1714.jpg" alt=""></a></div>

</div><!-- .carousel-slider-191 -->
</div><!-- .carousel-slider-outer-191 -->
</p>
<p></p>
<p><a href="https://github.com/vedmant/running-time">GitHub Link</a></p>
<p><a href="https://running-time.vedmant.com/">Demo</a></p>
<p>Use login: <code>user@gmail.com</code> and password: <code>123456</code></p>
<p>This project is fully free to use for any purpose and licenced under MIT License.</p>
<p>The post <a href="https://vedmant.com/sample-single-page-application-spa-using-laravel-5-vue2-vuex-vue-router/">Sample Single Page Application (SPA) using Laravel 5 &#038; Vue2 + Vuex + Vue-Router</a> appeared first on <a href="https://vedmant.com">vedmant.com :: coding blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://vedmant.com/sample-single-page-application-spa-using-laravel-5-vue2-vuex-vue-router/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Testing emails with Laravel</title>
		<link>https://vedmant.com/testing-emails-laravel/</link>
					<comments>https://vedmant.com/testing-emails-laravel/#respond</comments>
		
		<dc:creator><![CDATA[vedmant]]></dc:creator>
		<pubDate>Thu, 18 May 2017 12:32:34 +0000</pubDate>
				<category><![CDATA[Laravel]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Emails]]></category>
		<guid isPermaLink="false">https://vedmant.com/?p=172</guid>

					<description><![CDATA[<p>Reliability of emails subsystem is essential for current web applications, but testing emails is not as easy at it looks at first glance. Laravel doesn&#8217;t provide a good solution for testing emails out of the box, so after a bit of Googling I come up with following solution for testing emails. Helper Basic idea is &#8230; <a href="https://vedmant.com/testing-emails-laravel/" class="more-link">Continue reading <span class="screen-reader-text">Testing emails with Laravel</span></a></p>
<p>The post <a href="https://vedmant.com/testing-emails-laravel/">Testing emails with Laravel</a> appeared first on <a href="https://vedmant.com">vedmant.com :: coding blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Reliability of emails subsystem is essential for current web applications, but testing emails is not as easy at it looks at first glance. Laravel doesn&#8217;t provide a good solution for testing emails out of the box, so after a bit of Googling I come up with following solution for testing emails.</p>
<h3>Helper</h3>
<p>Basic idea is build on attaching event listener to Swift emails package, for this I extended base class <code>Swift_Events_EventListener</code> that takes as parameter our test case.</p>
<pre class="brush: php; title: ; notranslate">
/**
 * Class TestingMailEventListener
 *
 * @package Tests
 */
class TestingMailEventListener implements Swift_Events_EventListener
{
    protected $test;

    /**
     * TestingMailEventListener constructor.
     *
     * @param $test
     */
    public function __construct($test)
    {
        $this-&gt;test = $test;
    }

    /**
     * Before email sent
     * 
     * @param Swift_Events_SendEvent $event
     */
    public function beforeSendPerformed(Swift_Events_SendEvent $event)
    {
        $this-&gt;test-&gt;addEmail($event-&gt;getMessage());
    }
}
</pre>
<p>Then I created a Trait with following method:</p>
<pre class="brush: php; title: ; notranslate">
/**
 * Trait TracksEmails
 *
 * @package Tests
 */
trait TracksEmails
{
    /**
     * Delivered emails.
     * @var array
     */
    protected $emails = &#x5B;];

    /**
     * Register a listener for new emails.
     *
     * @before
     */
    public function setUpMailTracking()
    {
        Mail::getSwiftMailer()
            -&gt;registerPlugin(new TestingMailEventListener($this));
    }
...
</pre>
<p>Which registers event listener and collects all emails sent with Swift.</p>
<p>Having this done it&#8217;s easy to check whether particular email was sent, I also added bunch of helpers to make it easier:</p>
<pre class="brush: php; title: ; notranslate">
/**
 * Assert that at least one email was sent.
 * @return $this
 */
protected function seeEmailWasSent()

/**
 * Assert that the given number of emails were sent.
 *
 * @param integer $count
 * @return $this
 */
protected function seeEmailsSent($count)

/**
 * Assert that the last email's body contains the given text.
 *
 * @param string $excerpt
 * @param Swift_Mime_Message $message
 * @return $this
 */
protected function seeEmailContains($excerpt, Swift_Mime_Message $message = null)
...
</pre>
<p>And several more.</p>
<p>Here you can see full helper trait code <a href="https://gist.github.com/vedmant/57a908908457e160f5cab39cc7a93d5b"  target="_blank">click</a>.</p>
<h3>Usage</h3>
<p>Usage of this helper is quite simple, here is simple example:</p>
<pre class="brush: php; title: ; notranslate">
public function testEmail()
{
    \Mail::raw('Some content', function (Message $message) {
        $message-&gt;from('laravel@test.com', 'Laravel');
        $message-&gt;to('testmail@test.com');
    });

    $this-&gt;seeEmailWasSent()
        -&gt;seeEmailTo('testmail@test.com')
        -&gt;seeEmailContains('Some content');
}
</pre>
<p>And a bit more complex example of how I test my password reset form:</p>
<pre class="brush: php; title: ; notranslate">
public function testPasswordReset()
{
    $user = $this-&gt;makeUser();

    Event::listen(NotificationSent::class, function (NotificationSent $notification) use ($user) {
        self::$token = $notification-&gt;notification-&gt;token;
        $this-&gt;seeEmailWasSent()
            -&gt;seeEmailTo($user-&gt;Login)
            -&gt;seeEmailContains(self::$token);
    });

    $this-&gt;visitRoute('password.request')
        -&gt;assertResponseOk()
        -&gt;type($user-&gt;Login, 'email')
        -&gt;press('Reset')
        -&gt;assertResponseOk()
        -&gt;see(trans('passwords.sent'))
        -&gt;seeInDatabase('password_resets', &#x5B;'email' =&gt; $user-&gt;Login]);

    $this-&gt;visitRoute('password.reset', &#x5B;'token' =&gt; self::$token])
        -&gt;assertResponseOk()
        -&gt;type($user-&gt;Login, 'email')
        -&gt;type('123123', 'password')
        -&gt;type('123123', 'password_confirmation')
        -&gt;press('Reset Password')
        -&gt;assertResponseOk()
        -&gt;seeRouteIs('dashboard');

    $this-&gt;assertTrue($this-&gt;isAuthenticated());

    $this-&gt;assertTrue(app('hash')-&gt;check('123123', $user-&gt;fresh()-&gt;Password));
}
</pre>
<p>In this example I used events listener to listen for notification to check if sent token is the correct one.</p>
<p>Currently there are some probably better alternatives for testing emails with Laravel, like this one <a href="https://github.com/tightenco/mailthief" target="_blank">tightenco/mailthief</a>.</p>
<p>The post <a href="https://vedmant.com/testing-emails-laravel/">Testing emails with Laravel</a> appeared first on <a href="https://vedmant.com">vedmant.com :: coding blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://vedmant.com/testing-emails-laravel/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Why JavaScript &#8220;++[[]][+[]]+[+[]]&#8221; expression returns string &#8220;10&#8221;</title>
		<link>https://vedmant.com/javascript-expression-returns-string-10/</link>
					<comments>https://vedmant.com/javascript-expression-returns-string-10/#respond</comments>
		
		<dc:creator><![CDATA[vedmant]]></dc:creator>
		<pubDate>Sun, 14 May 2017 16:25:25 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Riddle]]></category>
		<guid isPermaLink="false">https://vedmant.com/?p=165</guid>

					<description><![CDATA[<p>Recently I came over quite interesting expressions ++[[]][+[]]+[+[]] and if you open browser JavaScript console and paste it there it will return string &#8220;10&#8221;, but how it really works? This is something that took my mind yesterday and I decided to make it clear for me: Firstly, +[] in JavaScript is the same as +"" &#8230; <a href="https://vedmant.com/javascript-expression-returns-string-10/" class="more-link">Continue reading <span class="screen-reader-text">Why JavaScript &#8220;++[[]][+[]]+[+[]]&#8221; expression returns string &#8220;10&#8221;</span></a></p>
<p>The post <a href="https://vedmant.com/javascript-expression-returns-string-10/">Why JavaScript &#8220;++[[]][+[]]+[+[]]&#8221; expression returns string &#8220;10&#8221;</a> appeared first on <a href="https://vedmant.com">vedmant.com :: coding blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Recently I came over quite interesting expressions <code>++[[]][+[]]+[+[]]</code> and if you open browser JavaScript console and paste it there it will return string &#8220;10&#8221;, but how it really works?</p>
<p>This is something that took my mind yesterday and I decided to make it clear for me:</p>
<ol>
<li>Firstly, <code>+[]</code> in JavaScript is the same as <code>+""</code> which casts a value to number 0, which is used twice, so if we replace it, we can now see following:
<pre class="brush: jscript; title: ; notranslate">
++&#x5B;&#x5B;]]&#x5B;0]+&#x5B;0]
</pre>
</p>
</li>
<li>
<p>Now we can split it to two three separate expressions:</p>
<pre class="brush: jscript; title: ; notranslate">
++ // Increment operator
&#x5B;&#x5B;]]&#x5B;0] // Which returns &#x5B;], that casts to 0 and then incremented to 1 (++ always returns a number)
+&#x5B;0] // Which returns 0
</pre>
</p>
</li>
<li>
<p><code>[[]][0]</code> means we get the first element from array <code>[[]]</code> which has one element that&#8217;s empty array and then increment it by 1, let&#8217;s write it in JS:</p>
<pre class="brush: jscript; title: ; notranslate">
&#x5B;&#x5B;]]&#x5B;0] // &#x5B;], or
&#x5B;&#x5B;]].pop() // &#x5B;]
</pre>
</p>
</li>
<li>
<p>Getting 1 from <code>++[[]][0]</code>, as we figured out <code>[[]][0]</code> basically means just empty array or, <code>[]</code>, then we have <code>[] + 1</code> which returns string &#8220;1&#8221;, and due to ++ always returns number, we have just number 1:</p>
<pre class="brush: jscript; title: ; notranslate">
++&#x5B;&#x5B;]]&#x5B;0] // 1
++&#x5B;&#x5B;]]&#x5B;0] === +(&#x5B;] + 1) // true
+(&#x5B;] + 1) === 1 // true
</pre>
</p>
</li>
<li>
<p>And the last part <code>+ [0]</code>, when we add array to anything in JavaScript, it will concatenate it to string of values with commas:</p>
<pre class="brush: jscript; title: ; notranslate">
0 + &#x5B;0, 1, 2, 3] // &quot;00,1,2,3&quot;
&#x5B;1,2] + &#x5B;3,4] // &quot;1,23,4&quot;

// Or in our case
1 + &#x5B;0] // &quot;10&quot; - Yay!
</pre>
</p>
</li>
</ol>
<p>To sum it up, lets describe it in single place:</p>
<pre class="brush: jscript; title: ; notranslate">
++ // Increment result of next expression, or make number 1
    &#x5B;
        &#x5B;] // Array with single empty array item
    ]
    &#x5B; // Use bracket expression to access 0 element of previous array, which is empty array &quot;&#x5B;]&quot;
        +&#x5B;] // Cast array to 0
    ]

+ // Unary + Operator, or 1 + &#x5B;0]

&#x5B; // Array with one element of number 0
    +&#x5B;] // Cast array to 0
]
</pre>
<p>The post <a href="https://vedmant.com/javascript-expression-returns-string-10/">Why JavaScript &#8220;++[[]][+[]]+[+[]]&#8221; expression returns string &#8220;10&#8221;</a> appeared first on <a href="https://vedmant.com">vedmant.com :: coding blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://vedmant.com/javascript-expression-returns-string-10/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Simple MySql daily and weekly backups on Linux</title>
		<link>https://vedmant.com/simple-mysql-daily-weekly-backups-linux/</link>
					<comments>https://vedmant.com/simple-mysql-daily-weekly-backups-linux/#respond</comments>
		
		<dc:creator><![CDATA[vedmant]]></dc:creator>
		<pubDate>Sat, 13 May 2017 21:51:02 +0000</pubDate>
				<category><![CDATA[Servers]]></category>
		<guid isPermaLink="false">https://vedmant.com/?p=153</guid>

					<description><![CDATA[<p>Recently I had a task to create automatic Mysql database backups daily and weekly and keep some number of those backups. After some short googling I come up with a quite small and simple shell script that just works. To make this happen we need few following steps: Create a new file in /etc/cron.daily/ folder &#8230; <a href="https://vedmant.com/simple-mysql-daily-weekly-backups-linux/" class="more-link">Continue reading <span class="screen-reader-text">Simple MySql daily and weekly backups on Linux</span></a></p>
<p>The post <a href="https://vedmant.com/simple-mysql-daily-weekly-backups-linux/">Simple MySql daily and weekly backups on Linux</a> appeared first on <a href="https://vedmant.com">vedmant.com :: coding blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Recently I had a task to create automatic Mysql database backups daily and weekly and keep some number of those backups.</p>
<p>After some short googling I come up with a quite small and simple shell script that just works.</p>
<p>To make this happen we need few following steps:</p>
<ol>
<li>Create a new file in <code>/etc/cron.daily/</code> folder with execute permission, supposed we switched to root user already
<pre class="brush: bash; title: ; notranslate">
touch /etc/cron.daily/db-backup-mydb
chmod 700 /etc/cron.daily/db-backup-mydb
vim /etc/cron.daily/db-backup-mydb
</pre>
<p>I used 700 permission so only root user can read the file, cause it will store password to our database</p>
</li>
<li>
<p>Press key &#8220;i&#8221; and paste the following code:</p>
<pre class="brush: bash; title: ; notranslate">
#!/bin/sh

# Setup some variables
backupfolder=&quot;/home/myapp/backup&quot;
user=&quot;user&quot;
prefix=&quot;db_daily_&quot;
now=&quot;$(date +'%Y%m%d-%H%M%S')&quot;
filename=&quot;$prefix$now.sql.gz&quot;
database=&quot;mydb&quot;
db_user=&quot;mydbuser&quot;
password=&quot;mypass&quot;

fullpathbackupfile=&quot;$backupfolder/$filename&quot;
logfile=&quot;$backupfolder/&quot;backup_log_&quot;$(date +'%Y_%m')&quot;.txt

# Do a backup
echo &quot;mysqldump started at $(date +'%Y-%m-%d %H:%M:%S')&quot; &gt;&gt; &quot;$logfile&quot;
mysqldump --user=$db_user --password=$password --default-character-set=utf8 --single-transaction $database | gzip &gt; &quot;$fullpathbackupfile&quot;
echo &quot;mysqldump finished at $(date +'%Y-%m-%d %H:%M:%S')&quot; &gt;&gt; &quot;$logfile&quot;

# Change file permission
chown $user:$user &quot;$fullpathbackupfile&quot;
chown $user:$user &quot;$logfile&quot;
echo &quot;file permission changed&quot; &gt;&gt; &quot;$logfile&quot;

# Delete backup files older than 8 days
find &quot;$backupfolder&quot; -name $prefix* -mtime +8 -exec rm {} \;
echo &quot;old files deleted&quot; &gt;&gt; &quot;$logfile&quot;
echo &quot;operation finished at $(date +'%Y-%m-%d %H:%M:%S')&quot; &gt;&gt; &quot;$logfile&quot;
echo &quot;*****************&quot; &gt;&gt; &quot;$logfile&quot;

exit 0
</pre>
<p>Also edit variables you need and replace database credentials at line starting with <code>mysqldump</code> after it press &#8220;Esc&#8221;.</p>
</li>
<li>
<p>Then save the file by pressing &#8220;:&#8221; (colon), then &#8220;wq&#8221; and press enter.</p>
</li>
<li>
<p>Run it to rest that it creates backups successfully:</p>
<pre class="brush: bash; title: ; notranslate">
/etc/cron.daily/db-backup-mydb
</pre>
<p>When you open your <code>/home/myapp/backups</code> folder you will see sql.gz backup file and a log file with debug information about backup process.</p>
</li>
</ol>
<p>To make weekly backups the only few things you need to change is to place the script into <code>/etc/cron.weekly/</code> folder, replace filename part &#8220;daily&#8221; to &#8220;weekly&#8221; and change &#8220;-mtime +8&#8221; to &#8220;-mtime +56&#8221; to keep last 8 weekly backups.</p>
<p>The post <a href="https://vedmant.com/simple-mysql-daily-weekly-backups-linux/">Simple MySql daily and weekly backups on Linux</a> appeared first on <a href="https://vedmant.com">vedmant.com :: coding blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://vedmant.com/simple-mysql-daily-weekly-backups-linux/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>MS SQL on Vagrant Ubuntu Homestead box for development on Laravel</title>
		<link>https://vedmant.com/ms-sql-vagrant-ubuntu-homestead-box-development-laravel/</link>
					<comments>https://vedmant.com/ms-sql-vagrant-ubuntu-homestead-box-development-laravel/#comments</comments>
		
		<dc:creator><![CDATA[vedmant]]></dc:creator>
		<pubDate>Thu, 02 Feb 2017 12:57:43 +0000</pubDate>
				<category><![CDATA[Laravel]]></category>
		<category><![CDATA[MSSql]]></category>
		<category><![CDATA[SqlSrv]]></category>
		<guid isPermaLink="false">https://vedmant.com/?p=135</guid>

					<description><![CDATA[<p>Hi everyone! Recently I had a chance to setup and successfully run development environment with Microsoft SQL Server on Laravel&#8217;s Homestead Vagrant box. I used Homestead installation per project. And here is how I&#8217;ve done it. Prepare Homestead box First step is to install Homestead for a project: composer require laravel/homestead --dev php vendor/bin/homestead make &#8230; <a href="https://vedmant.com/ms-sql-vagrant-ubuntu-homestead-box-development-laravel/" class="more-link">Continue reading <span class="screen-reader-text">MS SQL on Vagrant Ubuntu Homestead box for development on Laravel</span></a></p>
<p>The post <a href="https://vedmant.com/ms-sql-vagrant-ubuntu-homestead-box-development-laravel/">MS SQL on Vagrant Ubuntu Homestead box for development on Laravel</a> appeared first on <a href="https://vedmant.com">vedmant.com :: coding blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Hi everyone!</p>
<p>Recently I had a chance to setup and successfully run development environment with Microsoft SQL Server on Laravel&#8217;s Homestead Vagrant box. I used Homestead installation per project. And here is how I&#8217;ve done it.</p>
<h3>Prepare Homestead box</h3>
<p>First step is to install Homestead for a project:</p>
<pre class="brush: bash; title: ; notranslate">
composer require laravel/homestead --dev
php vendor/bin/homestead make
</pre>
<p>Then you need to change Homestead.yaml file.</p>
<p>Firstly, memory limit have to be changed to 4096: <code>memory: 4096</code></p>
<p>Then hostname: <code>hostname: mysite.dev</code></p>
<p>And probably name for convenience: &#8216;name: mysite.dev&#8217;</p>
<p>In <code>sites</code> section make sure that you have configuration like this:</p>
<pre class="brush: yaml; title: ; notranslate">
sites:
    - map: mysite.dev
      to: &quot;/home/vagrant/project/public&quot;
</pre>
<p>Then download and install Vagrant box</p>
<pre class="brush: plain; title: ; notranslate">
vagrant up
</pre>
<p>And add to hosts file domain for a this box <code>192.168.10.10 mysite.dev</code>.</p>
<h3>Install, setup and import database</h3>
<p>To setup database login to Vagrant box</p>
<pre class="brush: bash; title: ; notranslate">
vagrant ssh
</pre>
<p>Install MS SQL server and tools:</p>
<pre class="brush: bash; title: ; notranslate">
curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
curl https://packages.microsoft.com/config/ubuntu/16.04/mssql-server.list | sudo tee /etc/apt/sources.list.d/mssql-server.list
curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list | sudo tee /etc/apt/sources.list.d/msprod.list

sudo apt-get update
sudo apt-get install -y mssql-server
sudo apt-get install -y mssql-tools unixodbc-dev

sudo ln -sfn /opt/mssql-tools/bin/sqlcmd-13.0.1.0 /usr/bin/sqlcmd
sudo ln -sfn /opt/mssql-tools/bin/bcp-13.0.1.0 /usr/bin/bcp
</pre>
<p>Then run initial MS SQL setup script</p>
<pre class="brush: bash; title: ; notranslate">
sudo /opt/mssql/bin/mssql-conf setup
</pre>
<p>Use password &#8220;Secret123&#8221;, start server and enable starting on boot</p>
<p>Then it will require to install Sybase php extension</p>
<pre class="brush: bash; title: ; notranslate">
sudo apt-get install -y php7.1-sybase
</pre>
<p>When it will be updating some packages, select to keep the local version of config files on prompts.</p>
<p>To connect your Laravel application to MS SQL server you may need to add following configuration to your <code>config/database.php</code> file to <code>connections</code> section:</p>
<pre class="brush: php; title: ; notranslate">
'sqlsrv' =&gt; &#x5B;
    'driver' =&gt; 'sqlsrv',
    'host' =&gt; env('DB_HOST', 'localhost'),
    'database' =&gt; env('DB_DATABASE', 'forge'),
    'username' =&gt; env('DB_USERNAME', 'sa'),
    'password' =&gt; env('DB_PASSWORD', ''),
    'charset' =&gt; 'utf8',
    'prefix' =&gt; '',
],
</pre>
<p>After this application should be able to successfully connect to MS Sql server.</p>
<p>To import database, copy database *.BAK files to project folder, open sqlcmd console</p>
<pre class="brush: bash; title: ; notranslate">
sqlcmd -U sa -P 'Secret123'
</pre>
<p>and run following queries to import MYDB.BAK database backup file</p>
<pre class="brush: sql; title: ; notranslate">
RESTORE DATABASE &#x5B;mydb] FROM DISK='/home/vagrant/project/MYDB.BAK'
WITH  FILE = 1,  
MOVE N'MYDB_dat' TO N'/var/opt/mssql/data/mydb.mdf',
MOVE N'MYDB_log' TO N'/var/opt/mssql/data/mydb.ldf',
NOUNLOAD,  REPLACE,  STATS = 1
GO
</pre>
<p>That&#8217;s basically all to install and run MS SQL on your Homestead Vagrant box, if you have any questions, feel free to contact!</p>
<p>The post <a href="https://vedmant.com/ms-sql-vagrant-ubuntu-homestead-box-development-laravel/">MS SQL on Vagrant Ubuntu Homestead box for development on Laravel</a> appeared first on <a href="https://vedmant.com">vedmant.com :: coding blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://vedmant.com/ms-sql-vagrant-ubuntu-homestead-box-development-laravel/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
	</channel>
</rss>
