Vous êtes sur la page 1sur 40

Write(https://pub.scotch.io/write) Slack(http://slack.scotch.io) Shop(http://shop.scotch.

io)
Topshelfwebdevelopertraining.
About(https://scotch.io/about) Login/Register

Menu
scotch
(https://scotch.io)
Subscribe & get our FREE eBook
Build Your First Node.js App

Email Address

Free Node Book

Stalk Us


(https://twitter.com/scotch_io)
laravel(https://scotch.io/tag/laravel) php(https://scotch.io/tag/php)


Working with JSON in (https://www.facebook.com/scotchdeve

MySQL
(https://github.com/scotch-io)
LearnhowtouseandqueryJSONdatainyour
MYSQLdatabases.

(https://feeds.feedblitz.com/scotch_io)
(https://pub.scotch.io/@nomanurrehman)

NomanUrRehman (https://pub.scotch.io/@nomanurrehman) Jan26,2017


Monthly Best
Tutorials(https://scotch.io/tutorials)
Comments(https://scotch.io/tutorials/working-with-json-in-mysql#disqus_thread)

12,461

RELATEDCOURSE

GET STARTED WITH JAVASCRIPT FOR WEB DEVELOPMENT


(https://hrd.cm/2k90ljr)
JavaScriptisthelanguageonfire.Buildanappforanyplatformyouwantincluding
website,server,mobile,anddesktop.

Get Started
)

(https://bit.ly/2koLun3)
ps
hi
ps

rs
hi

so
rs

on
so

sp
on

e/
Sp

yp
/t
.io
ch
ot
sc
//
s:
)
ps
hi
ps

rs
hi

so
rs

on
so

sp
on

e/
Sp

yp
SQLdatabasestendtoberigid.

/t
io
h.
tc
co
/s
:/
ps
tt
(h
Ifyouhaveworkedwiththem,youwouldagreethatdatabase
designthoughitseemseasier,isalottrickierinpractice.SQL
databasesbelieveinstructure,thatiswhyit'scalledstructured
querylanguage.

Ontheothersideofthehorizon,wehavetheNoSQLdatabases,
alsocalledschema-lessdatabasesthatencourageflexibility.In
schema-lessdatabases,thereisnoimposedstructuralrestriction,
Best Courses

onlydatatobesaved.

Thougheverytoolhasit'susecase,sometimesthingscallfora
hybridapproach.

Whatifyoucouldstructuresomepartsofyourdatabaseandleave
otherstobeflexible?

MySQLversion5.7.8
(https://dev.mysql.com/doc/relnotes/mysql/5.7/en/news-5-7-
8.html)introducesaJSONdatatypethatallowsyoutoaccomplish
that.

Inthistutorial,youaregoingtolearn.

1.HowtodesignyourdatabasetablesusingJSONfields.

2.ThevariousJSONbasedfunctionsavailableinMYSQLto ()
create,read,update,anddeleterows.

3.HowtoworkwithJSONfieldsusingtheEloquentORMin
Laravel.

# Why Use JSON


Atthismoment,youareprobablyaskingyourselfwhywouldyou
wanttouseJSONwhenMySQLhasbeencateringtoawidevariety
ofdatabaseneedsevenbeforeitintroducedaJSONdatatype.
(https://hrd.cm/2k90ljr)
Theanswerliesintheuse-caseswhereyouwouldprobablyusea
make-shiftapproach.

Letmeexplainwithanexample.
Supposeyouarebuildingawebapplicationwhereyouhavetosave
auser'sconfiguration/preferencesinthedatabase.

Generally,youcancreateaseparatedatabasetablewiththe id ,
user_id , key ,and value fieldsorsaveitasaformattedstringthat
youcanparseatruntime.

However,thisworkswellforasmallnumberofusers.Ifyouhave
aboutathousandusersandfiveconfigurationkeys,youare
lookingatatablewithfivethousandrecordsthataddressesavery
smallfeatureofyourapplication.

Orifyouaretakingtheformattedstringroute,extraneouscode
thatonlycompoundsyourserverload.

UsingaJSONdatatypefieldtosaveauser'sconfigurationinsucha
scenariocanspareyouadatabasetable'sspaceandbringdown
thenumberofrecords,whichwerebeingsavedseparately,tobe
thesameasthenumberofusers.

AndyougettheaddedbenefitofnothavingtowriteanyJSON
parsingcode,theORMorthelanguageruntimetakescareofit.

# The Schema
BeforewediveintousingallthecoolJSONstuffinMySQL,weare
goingtoneedasampledatabasetoplaywith.

So,let'sgetourdatabaseschemaoutofthewayfirst.

Wearegoingtoconsidertheusecaseofanonlinestorethat
housesmultiplebrandsandavarietyofelectronics.

Sincedifferentelectronicshavedifferentattributes(comparea
MacbookwithaVacuumnCleaner)thatbuyersareinterestedin, (https://hrd.cm/2k90ljr)
HIRED
typicallytheEntityattributevaluemodel(EAV)
(https://en.wikipedia.org/wiki/Entity%E2%80%93attribute%E2%80%93value_model)
(https://hrd.cm/2k90ljr) Hired is the absolute best way to nd a tech or

design job.
patternisused.
(https://twitter.com/intent/tweet?url=https%3A%2F%2Fscotch.io%2Ftutorials%2Fworking-with-json-in- Get Hired.

mysql&text=Working+with+JSON+in+MySQL&via=scotch_io&related=scotch_io)
However,sincewenowhavetheoptiontouseaJSONdatatype,we
Subscribe & get our FREE eBook

aregoingtodropEAV.
Build Your First Node.js App
Forastart,ourdatabasewillbenamed e_store andhasthree

Email Address
tablesonlynamed, brands , categories ,and products respectively.

Free Node Book

Our brands and categories tableswillbeprettysimilar,eachhaving


an id anda name field.

SQL

CREATE DATABASE IF NOT EXISTS `e_store`


DEFAULT CHARACTER SET utf8
DEFAULT COLLATE utf8_general_ci;

SET default_storage_engine = INNODB;

CREATE TABLE `e_store`.`brands`(


`id` INT UNSIGNED NOT NULL auto_increment ,
`name` VARCHAR(250) NOT NULL ,
PRIMARY KEY(`id`)
);

CREATE TABLE `e_store`.`categories`(


`id` INT UNSIGNED NOT NULL auto_increment ,
`name` VARCHAR(250) NOT NULL ,
PRIMARY KEY(`id`)
);

Theobjectiveofthesetwotableswillbetohousetheproduct
categoriesandthebrandsthatprovidetheseproducts.

Whileweareatit,letusgoaheadandseedsomedataintothese
tablestouselater.
FIND YOUR
OPPORTUNITY

HIRED

(https://hrd.cm/2k90ljr)
SQL

/* Brands */
INSERT INTO `e_store`.`brands`(`name`)
VALUES
('Samsung');

INSERT INTO `e_store`.`brands`(`name`)


VALUES
('Nokia');

INSERT INTO `e_store`.`brands`(`name`)


VALUES
('Canon');

/* Types of electronic device */


INSERT INTO `e_store`.`categories`(`name`)
VALUES
('Television');

INSERT INTO `e_store`.`categories`(`name`)


VALUES
('Mobilephone');

INSERT INTO `e_store`.`categories`(`name`)


VALUES
('Camera');

Next,isthebusinessareaofthistutorial.

Wearegoingtocreatea products tablewiththe id , name , brand_id ,


category_id ,and attributes fields.

(https://hrd.cm/2k90ljr)
SQL

CREATE TABLE `e_store`.`products`(


`id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`name` VARCHAR(250) NOT NULL ,
`brand_id` INT UNSIGNED NOT NULL ,
`category_id` INT UNSIGNED NOT NULL ,
`attributes` JSON NOT NULL ,
PRIMARY KEY(`id`) ,
INDEX `CATEGORY_ID`(`category_id` ASC) ,
INDEX `BRAND_ID`(`brand_id` ASC) ,
CONSTRAINT `brand_id` FOREIGN KEY(`brand_id`) REFERENCES `e_store`.`brands
CONSTRAINT `category_id` FOREIGN KEY(`category_id`) REFERENCES `e_store
);

Ourtabledefinitionspecifiesforeignkeyconstraintsforthe
brand_id and category_id fields,specifyingthattheyreferencethe
brands and categories tablerespectively.Wehavealsospecifiedthat
thereferencedrowsshouldnotbeallowedtodeleteandif
updated,thechangesshouldreflectinthereferencesaswell.

The attributes field'scolumntypehasbeendeclaredtobeJSON


whichisthenativedatatypenowavailableinMySQL.Thisallowsus
tousethevariousJSONrelatedconstructsinMySQLonour
attributes field.

Hereisanentityrelationshipdiagramofourcreateddatabase.

(https://hrd.cm/2k90ljr)
Ourdatabasedesignisnotthebest
intermsofefficiencyandaccuracy.
Thereisnopricecolumninthe
products tableandwecoulddowith

puttingaproductintomultiple
categories.However,thepurposeof
thistutorialisnottoteachdatabase
designbutratherhowtomodel
objectsofdifferentnatureinasingle
tableusingMySQL'sJSONfeatures.

(https://hrd.cm/2k90ljr)
# The CRUD Operations
Letuslookathowtocreate,read,update,anddeletedataina
JSONfield.

CREATE
CreatingarecordinthedatabasewithaJSONfieldisprettysimple.

AllyouneedtodoisaddvalidJSONasthefieldvalueinyourinsert
statement.

(https://hrd.cm/2k90ljr)
SQL

/* Let's sell some televisions */


INSERT INTO `e_store`.`products`(
`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Prime' ,
'1' ,
'1' ,
'{"screen": "50 inch", "resolution": "2048 x 1152 pixels", "ports": {"hdmi": 1, "usb": 3}, "speakers": {"left": "
);

INSERT INTO `e_store`.`products`(


`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Octoview' ,
'1' ,
'1' ,
'{"screen": "40 inch", "resolution": "1920 x 1080 pixels", "ports": {"hdmi": 1, "usb": 2}, "speakers": {"left": "
);

INSERT INTO `e_store`.`products`(


`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Dreamer' ,
'1' ,
'1' ,
'{"screen": "30 inch", "resolution": "1600 x 900 pixles", "ports": {"hdmi": 1, "usb": 1}, "speakers": {"left": "1
);

(https://hrd.cm/2k90ljr)
INSERT INTO `e_store`.`products`(
`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Bravia' ,
'1' ,
'1' ,
'{"screen": "25 inch", "resolution": "1366 x 768 pixels", "ports": {"hdmi": 1, "usb": 0}, "speakers": {"left": "5
);

INSERT INTO `e_store`.`products`(


`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Proton' ,
'1' ,
'1' ,
'{"screen": "20 inch", "resolution": "1280 x 720 pixels", "ports": {"hdmi": 0, "usb": 0}, "speakers": {"left": "5
);

InsteadoflayingouttheJSONobjectyourself,youcanalsousethe
built-in JSON_OBJECT function.

The JSON_OBJECT functionacceptsalistofkey/valuepairsintheform


JSON_OBJECT(key1, value1, key2, value2, ... key(n), value(n)) andreturnsa
JSONobject.

(https://hrd.cm/2k90ljr)
SQL

/* Let's sell some mobilephones */


INSERT INTO `e_store`.`products`(
`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Desire' ,
'2' ,
'2' ,
JSON_OBJECT(
"network" ,
JSON_ARRAY("GSM" , "CDMA" , "HSPA" , "EVDO") ,
"body" ,
"5.11 x 2.59 x 0.46 inches" ,
"weight" ,
"143 grams" ,
"sim" ,
"Micro-SIM" ,
"display" ,
"4.5 inches" ,
"resolution" ,
"720 x 1280 pixels" ,
"os" ,
"Android Jellybean v4.3"
)
);

INSERT INTO `e_store`.`products`(


`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Passion' ,
'2' ,
'2' ,
JSON_OBJECT(
(https://hrd.cm/2k90ljr)
"network" ,
JSON_ARRAY("GSM" , "CDMA" , "HSPA") ,
"body" ,
"6.11 x 3.59 x 0.46 inches" ,
"weight" ,
"145 grams" ,
"sim" ,
"Micro-SIM" ,
"display" ,
"4.5 inches" ,
"resolution" ,
"720 x 1280 pixels" ,
"os" ,
"Android Jellybean v4.3"
)
);

INSERT INTO `e_store`.`products`(


`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Emotion' ,
'2' ,
'2' ,
JSON_OBJECT(
"network" ,
JSON_ARRAY("GSM" , "CDMA" , "EVDO") ,
"body" ,
"5.50 x 2.50 x 0.50 inches" ,
"weight" ,
"125 grams" ,
"sim" ,
"Micro-SIM" ,
"display" ,
"5.00 inches" ,
"resolution" ,
"720 x 1280 pixels" ,
"os" ,
"Android KitKat v4.3"
)
);

INSERT INTO `e_store`.`products`(


`name` ,
`brand_id` ,
(https://hrd.cm/2k90ljr)
`category_id` ,
`attributes`
)
VALUES(
'Sensation' ,
'2' ,
'2' ,
JSON_OBJECT(
"network" ,
JSON_ARRAY("GSM" , "HSPA" , "EVDO") ,
"body" ,
"4.00 x 2.00 x 0.75 inches" ,
"weight" ,
"150 grams" ,
"sim" ,
"Micro-SIM" ,
"display" ,
"3.5 inches" ,
"resolution" ,
"720 x 1280 pixels" ,
"os" ,
"Android Lollypop v4.3"
)
);

INSERT INTO `e_store`.`products`(


`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Joy' ,
'2' ,
'2' ,
JSON_OBJECT(
"network" ,
JSON_ARRAY("CDMA" , "HSPA" , "EVDO") ,
"body" ,
"7.00 x 3.50 x 0.25 inches" ,
"weight" ,
"250 grams" ,
"sim" ,
"Micro-SIM" ,
"display" ,
"6.5 inches" ,
"resolution" ,
"1920 x 1080 pixels" ,
(https://hrd.cm/2k90ljr)
"os" ,
"Android Marshmallow v4.3"
)
);
Noticethe JSON_ARRAY functionwhichreturnsaJSONarraywhen
passedasetofvalues.

Ifyouspecifyasinglekeymultipletimes,onlythefirstkey/value
pairwillberetained.ThisiscallednormalizingtheJSONinMySQL's
terms.Also,aspartofnormalization,theobjectkeysaresortedand
theextrawhite-spacebetweenkey/valuepairsisremoved.

AnotherfunctionthatwecanusetocreateJSONobjectsisthe
JSON_MERGE function.

The JSON_MERGE functiontakesmultipleJSONobjectsandproducesa


single,aggregateobject.

(https://hrd.cm/2k90ljr)
SQL

/* Let's sell some cameras */


INSERT INTO `e_store`.`products`(
`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Explorer' ,
'3' ,
'3' ,
JSON_MERGE(
'{"sensor_type": "CMOS"}' ,
'{"processor": "Digic DV III"}' ,
'{"scanning_system": "progressive"}' ,
'{"mount_type": "PL"}' ,
'{"monitor_type": "LCD"}'
)
);

INSERT INTO `e_store`.`products`(


`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Runner' ,
'3' ,
'3' ,
JSON_MERGE(
JSON_OBJECT("sensor_type" , "CMOS") ,
JSON_OBJECT("processor" , "Digic DV II") ,
JSON_OBJECT("scanning_system" , "progressive") ,
JSON_OBJECT("mount_type" , "PL") ,
JSON_OBJECT("monitor_type" , "LED")
)
);

INSERT INTO `e_store`.`products`(


(https://hrd.cm/2k90ljr)
`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Traveler' ,
'3' ,
'3' ,
JSON_MERGE(
JSON_OBJECT("sensor_type" , "CMOS") ,
'{"processor": "Digic DV II"}' ,
'{"scanning_system": "progressive"}' ,
'{"mount_type": "PL"}' ,
'{"monitor_type": "LCD"}'
)
);

INSERT INTO `e_store`.`products`(


`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Walker' ,
'3' ,
'3' ,
JSON_MERGE(
'{"sensor_type": "CMOS"}' ,
'{"processor": "Digic DV I"}' ,
'{"scanning_system": "progressive"}' ,
'{"mount_type": "PL"}' ,
'{"monitor_type": "LED"}'
)
);

INSERT INTO `e_store`.`products`(


`name` ,
`brand_id` ,
`category_id` ,
`attributes`
)
VALUES(
'Jumper' ,
'3' ,
'3' ,
JSON_MERGE(
(https://hrd.cm/2k90ljr)
'{"sensor_type": "CMOS"}' ,
'{"processor": "Digic DV I"}' ,
'{"scanning_system": "progressive"}' ,
'{"mount_type": "PL"}' ,
'{"monitor_type": "LCD"}'
)
);

Thereisalothappeningintheseinsertstatementsanditcangeta
bitconfusing.However,itisprettysimple.

Weareonlypassingobjectstothe JSON_MERGE function.Someof


themhavebeenconstructedusingthe JSON_OBJECT functionwesaw
previouslywhereasothershavebeenpassedasvalidJSONstrings.

Incaseofthe JSON_MERGE function,ifakeyisrepeatedmultiple


times,it'svalueisretainedasanarrayintheoutput.

AproofofconceptisinorderIsuppose.

SQL

/* output: {"network": ["GSM", "CDMA", "HSPA", "EVDO"]} */


SELECT JSON_MERGE(
'{"network": "GSM"}' ,
'{"network": "CDMA"}' ,
'{"network": "HSPA"}' ,
'{"network": "EVDO"}'
);

Wecanconfirmallourquerieswererunsuccessfullyusingthe
JSON_TYPE functionwhichgivesusthefieldvaluetype.

(https://hrd.cm/2k90ljr)
SQL

/* output: OBJECT */
SELECT JSON_TYPE(attributes) FROM `e_store`.`products`;

READ
Right,wehaveafewproductsinourdatabasetoworkwith.

FortypicalMySQLvaluesthatarenotoftypeJSON,awhereclause
isprettystraight-forward.Justspecifythecolumn,anoperator,and
thevaluesyouneedtoworkwith.

Heuristically,whenworkingwithJSONcolumns,thisdoesnotwork.

SQL

/* It's not that simple */


SELECT
*
FROM
`e_store`.`products`
WHERE
attributes = '{"ports": {"usb": 3, "hdmi": 1}, "screen": "50 inch", "speakers": {"left": "10 watt", "right": "10

WhenyouwishtonarrowdownrowsusingaJSONfield,youshould
befamiliarwiththeconceptofapathexpression.
(https://hrd.cm/2k90ljr)
Themostsimplestdefinitionofapathexpression(thinkJQuery
selectors)isit'susedtospecifywhichpartsoftheJSONdocument
toworkwith.
Thesecondpieceofthepuzzleisthe JSON_EXTRACT functionwhich
acceptsapathexpressiontonavigatethroughJSON.

Letussayweareinterestedintherangeoftelevisionsthathave
atleastasingleUSBandHDMIport.

SQL

SELECT
*
FROM
`e_store`.`products`
WHERE
`category_id` = 1
AND JSON_EXTRACT(`attributes` , '$.ports.usb') > 0
AND JSON_EXTRACT(`attributes` , '$.ports.hdmi') > 0;

Thefirstargumenttothe JSON_EXTRACT functionistheJSONtoapply


thepathexpressiontowhichisthe attributes column.The $

symboltokenizestheobjecttoworkwith.The $.ports.usb and


$.ports.hdmi pathexpressionstranslateto"taketheusbkeyunder
ports"and"takethehdmikeyunderports"respectively.

Oncewehaveextractedthekeysweareinterestedin,itispretty
simpletousetheMySQLoperatorssuchas > onthem.

Also,the JSON_EXTRACT functionhasthealias -> thatyoucanuseto


makeyourqueriesmorereadable.

Revisingourpreviousquery.

(https://hrd.cm/2k90ljr)
SQL

SELECT
*
FROM
`e_store`.`products`
WHERE
`category_id` = 1
AND `attributes` -> '$.ports.usb' > 0
AND `attributes` -> '$.ports.hdmi' > 0;

UPDATE
InordertoupdateJSONvalues,wearegoingtousethe JSON_INSERT ,
JSON_REPLACE ,and JSON_SET functions.Thesefunctionsalsorequirea
pathexpressiontospecifywhichpartsoftheJSONobjectto
modify.

TheoutputofthesefunctionsisavalidJSONobjectwiththe
changesapplied.

Letusmodifyallmobilephonestohaveachipsetpropertyaswell.

SQL

UPDATE `e_store`.`products`
SET `attributes` = JSON_INSERT(
`attributes` ,
'$.chipset' ,
'Qualcomm'
)
WHERE
`category_id` = 2;

(https://hrd.cm/2k90ljr)
The $.chipset pathexpressionidentifiesthepositionofthe chipset

propertytobeattherootoftheobject.

Letusupdatethe chipset propertytobemoredescriptiveusingthe


JSON_REPLACE function.

SQL

UPDATE `e_store`.`products`
SET `attributes` = JSON_REPLACE(
`attributes` ,
'$.chipset' ,
'Qualcomm Snapdragon'
)
WHERE
`category_id` = 2;

Easypeasy!

Lastly,wehavethe JSON_SET functionwhichwewillusetospecify


ourtelevisionsareprettycolorful.

SQL

UPDATE `e_store`.`products`
SET `attributes` = JSON_SET(
`attributes` ,
'$.body_color' ,
'red'
)
WHERE
`category_id` = 1;

(https://hrd.cm/2k90ljr)
Allofthesefunctionsseemidenticalbutthereisadifferenceinthe
waytheybehave.

The JSON_INSERT functionwillonlyaddthepropertytotheobjectifit


doesnotexistsalready.

The JSON_REPLACE functionsubstitutesthepropertyonlyifitisfound.

The JSON_SET functionwilladdthepropertyifitisnotfoundelse


replaceit.

DELETE
Therearetwopartstodeletingthatwewilllookat.

Thefirstistodeleteacertainkey/valuefromyourJSONcolumns
whereasthesecondistodeleterowsusingaJSONcolumn.

Letussaywearenolongerprovidingthe mount_type informationfor


camerasandwishtoremoveitforallcameras.

Wewilldoitusingthe JSON_REMOVE functionwhichreturnsthe


updatedJSONafterremovingthespecifiedkeybasedonthepath
expression.

SQL

UPDATE `e_store`.`products`
SET `attributes` = JSON_REMOVE(`attributes` , '$.mount_type')
WHERE
`category_id` = 3;

Forthesecondcase,wealsodonotprovidemobilephones
(https://hrd.cm/2k90ljr)
anymorethathavetheJellybeanversionoftheAndroidOS.
SQL

DELETE FROM `e_store`.`products`


WHERE `category_id` = 2
AND JSON_EXTRACT(`attributes` , '$.os') LIKE '%Jellybean%';

Asstatedpreviously,workingwithaspecificattributerequiresthe
useofthe JSON_EXTRACT functionsoinordertoapplythe LIKE

operator,wehavefirstextractedthe os propertyof
mobilephones(withthehelpof category_id )anddeletedallrecords
thatcontainthestring Jellybean .

# A Primer for Web Applications


Theolddaysofdirectlyworkingwithadatabasearewaybehindus.

Thesedays,frameworksinsulatedevelopersfromlower-level
operationsanditalmostfeelsalienforaframeworkfanaticnotto
beabletotranslatehis/herdatabaseknowledgeintoanobject
relationalmapper.

Forthepurposeofnotleavingsuchdevelopersheartbrokenand
wonderingabouttheirexistenceandpurposeintheuniverse,we
aregoingtolookathowtogoaboutthebusinessofJSONcolumns
intheLaravelframework.

(https://hrd.cm/2k90ljr)
Wewillonlybefocusingontheparts
thatoverlapwithoursubjectmatter
whichdealswithJSONcolumns.An
in-depthtutorialontheLaravel
frameworkisbeyondthescopeof
thispiece.

# Creating the Migrations


MakesuretoconfigureyourLaravelapplicationtouseaMySQL
database.

Wearegoingtocreatethreemigrationsfor brands , categories ,and


products respectively.

BASH

$ php artisan make:migration create_brands


$ php artisan make:migration create_categories
$ php artisan make:migration create_products

The create_brands and create_categories migrationsareprettysimilar


andandaregulationforLaraveldevelopers.

(https://hrd.cm/2k90ljr)
PHP

/* database/migrations/create_brands.php */

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateBrands extends Migration


{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('brands', function(Blueprint $table){
$table->engine = 'InnoDB';
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('brands');
}
}

/* database/migrations/create_categories.php */

<?php

(https://hrd.cm/2k90ljr)
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateCategories extends Migration


{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('categories', function(Blueprint $table){
$table->engine = 'InnoDB';
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('categories');
}
}

The create_products migrationwillalsohavethedirectivesfor


indexesandforeignkeys.

(https://hrd.cm/2k90ljr)
PHP

/* database/migrations/create_products */

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateProducts extends Migration


{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('products', function(Blueprint $table){
$table->engine = 'InnoDB';
$table->increments('id');
$table->string('name');
$table->unsignedInteger('brand_id');
$table->unsignedInteger('category_id');
$table->json('attributes');
$table->timestamps();
// foreign key constraints
$table->foreign('brand_id')->references('id')->on('brands')->
$table->foreign('category_id')->references('id')->on('categories'
// indexes
$table->index('brand_id');
$table->index('category_id');
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
(https://hrd.cm/2k90ljr)
{
Schema::drop('products');
}
}
Payattentiontothe $table->json('attributes'); statementinthe
migration.

Justlikecreatinganyothertablefieldusingtheappropriatedata
typenamedmethod,wehavecreatedaJSONcolumnusingthe
json methodwiththename attributes .

Also,thisonlyworksfordatabaseenginesthatsupporttheJSON
datatype.

Engines,suchasolderversionsofMySQLwillnotbeabletocarry
outthesemigrations.

# Creating the Models


Otherthanassociations,thereisnotmuchneededtosetupour
modelssolet'srunthroughthemquickly.

(https://hrd.cm/2k90ljr)
PHP

/* app/Brand.php */

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Brand extends Model


{
// A brand has many products
public function products(){
return $this->hasMany('Product')
}
}

/* app/Category.php */

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Category extends Model


{
// A category has many products
public function products(){
return $this->hasMany('Product')
}
}

/* app/Product.php */

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

(https://hrd.cm/2k90ljr)
class Product extends Model
{
// Cast attributes JSON to array
protected $casts = [
'attributes' => 'array'
];

// Each product has a brand


public function brand(){
return $this->belongsTo('Brand');
}

// Each product has a category


public function category(){
return $this->belongsTo('Category');
}
}

Again,our Product modelneedsaspecialmention.

The $casts arraywhichhasthekey attributes setto array makes


surewheneveraproductisfetchedfromthedatabase,it's
attributes JSONisconvertedtoanassociatedarray.

Wewillseelaterinthetutorialhowthisfacilitatesustoupdate
recordsfromourcontrolleractions.

# Resource Operations

CREATING A PRODUCT
Speakingoftheadminpanel,theparameterstocreateaproduct
maybecominginthroughdifferentroutessincewehaveanumber
ofproductcategories.Youmayalsohavedifferentviewstocreate,
edit,show,anddeleteaproduct.

Forexample,aformtoaddacamerarequiresdifferentinputfields
thanaformtoaddamobilephonesotheywarrantseparateviews.

(https://hrd.cm/2k90ljr)
Moreover,onceyouhavetheuserinputdata,youwillmost
probabalyrunitthrougharequestvalidator,separateforthe
camera,andthemobilephoneeach.

ThefinalstepwouldbetocreatetheproductthroughEloquent.
Wewillbefocusingonthecameraresourcefortherestofthis
tutorial.Otherproductscanbeaddressedusingthecodeproduced
inasimilarmanner.

Assumingwearesavingacameraandtheformfieldsarenamed
astherespectivecameraattributes,hereisthecontrolleraction.

PHP

// creates product in database


// using form fields
public function store(Request $request){
// create object and set properties
$camera = new \App\Product();
$camera->name = $request->name;
$camera->brand_id = $request->brand_id;
$camera->category_id = $request->category_id;
$camera->attributes = json_encode([
'processor' => $request->processor,
'sensor_type' => $request->sensor_type,
'monitor_type' => $request->monitor_type,
'scanning_system' => $request->scanning_system,
]);
// save to database
$camera->save();
// show the created camera
return view('product.camera.show', ['camera' => $camera]);
}

FETCHING PRODUCTS
Recallthe $casts arraywedeclaredearlierinthe Product model.It
willhelpusreadandeditaproductbytreatingattributesasan
associativearray.

(https://hrd.cm/2k90ljr)
PHP

// fetches a single product


// from database
public function show($id){
$camera = \App\Product::find($id);
return view('product.camera.show', ['camera' => $camera]);
}

Yourviewwouldusethe $camera variableinthefollowingmanner.

(https://hrd.cm/2k90ljr)
HTML

<table>
<tr>
<td>Name</td>
<td>{{ $camera->name }}</td>
</tr>
<tr>
<td>Brand ID</td>
<td>{{ $camera->brand_id }}</td>
</tr>
<tr>
<td>Category ID</td>
<td>{{ $camera->category_id }}</td>
</tr>
<tr>
<td>Processor</td>
<td>{{ $camera->attributes['processor'] }}</td>
</tr>
<tr>
<td>Sensor Type</td>
<td>{{ $camera->attributes['sensor_type'] }}</td>
</tr>
<tr>
<td>Monitor Type</td>
<td>{{ $camera->attributes['monitor_type'] }}</td>
</tr>
<tr>
<td>Scanning System</td>
<td>{{ $camera->attributes['scanning_system'] }}</td>
</tr>
</table>

EDITING A PRODUCT
Asshownintheprevioussection,youcaneasilyfetchaproduct
andpassittotheview,whichinthiscasewouldbetheeditview.

(https://hrd.cm/2k90ljr)
Youcanusetheproductvariabletopre-populateformfieldsonthe
editpage.
Updatingtheproductbasedontheuserinputwillbeprettysimilar
tothe store actionwesawearlier,onlythatinsteadofcreatinga
newproduct,youwillfetchitfirstfromthedatabasebefore
updatingit.

SEARCHING BASED ON JSON ATTRIBUTES


Thelastpieceofthepuzzlethatremainstodiscussisquerying
JSONcolumnsusingtheEloquentORM.

Ifyouhaveasearchpagethatallowscamerastobesearched
basedontheirspecificationsprovidedbytheuser,youcandoso
withthefollowingcode.

PHP

// searches cameras by user provided specifications


public function search(Request $request){
$cameras = \App\Product::where([
['attributes->processor', 'like', $request->processor],
['attributes->sensor_type', 'like', $request->sensor_type],
['attributes->monitor_type', 'like', $request->monitor_type],
['attributes->scanning_system', 'like', $request->scanning_system
])->get();
return view('product.camera.search', ['cameras' => $cameras]);
}

Theretrivedrecordswillnowbeavailabletothe product.camera.search

viewasa $cameras collection.

DELETING A PRODUCT
Usinganon-JSONcolumnattribute,youcandeleteproductsby
specifyingawhereclauseandthencallingthe delete method.

Forexample,incaseofanID.
(https://hrd.cm/2k90ljr)
PHP

\App\Product::where('id', $id)->delete();

ForJSONcolumns,specifyawhereclauseusingasingleormultiple
attributesandthencallthe delete method.

PHP

// deletes all cameras with the sensor_type attribute as CMOS


\App\Product::where('attributes->sensor_type', 'CMOS')->delete();
}

# Curtains
WehavebarelyscratchedthesurfacewhenitcomestousingJSON
columnsinMySQL.

Wheneveryouneedtosavedataaskey/valuepairsinaseparate
tableorworkwithflexibleattributesforanentity,youshould
considerusingaJSONdatatypefieldinsteadasitcanheavily
contributetocompressingyourdatabasedesign.

Ifyouareinterestedindivingdeeper,theMySQLdocumentation
(https://dev.mysql.com/doc/refman/5.7/en/json.html)isagreat
resourcetoexploreJSONconceptsfuther.

Ihopeyoufoundthistutorialinterestingandknowledgeable.Until
mynextpiece,happycoding!
(https://hrd.cm/2k90ljr)
laravel(https://scotch.io/tag/laravel) php(https://scotch.io/tag/php)

(https://pub.scotch.io/@nomanurrehman)

Noman Ur Rehman MyScotchPosts


(https://pub.scotch.io/@nomanurrehman)
Iamafullstack,freelancewebdeveloperwhospecializesinLaravel,
Rails,andAmazonWebServices.IloveRegularExpressionsand

discussingideas.
(https://pub.scotch.io/@nomanurrehman) (https://twitter.com/nomanurrehman)

(https://github.com/nomanurrehman)

Next Up

Laravel Random Keys with Keygen


Whendevelopingapplications,itisusuallycommontoseerandomnesscomeintoplay-and
asaresult,many...

(https://scotch.io/tutorials/laravel-random-keys-with-keygen)
API(https://scotch.io/tag/api) composer(https://scotch.io/tag/composer) laravel(https://scotch.io/tag/laravel) php
(https://pub.scotch.io/@gladchinda)
(https://scotch.io/tag/php) tokens(https://scotch.io/tag/tokens)

(https://hrd.cm/2k90ljr)

Quick Tip: Display Dates Relatively in Laravel


WehavepreviouslylookedattheCarbonpackagebyBrianNesbittaswellasallthe
functionality...
(https://scotch.io/tutorials/quick-tip-display-dates-relatively-in-laravel)
(https://pub.scotch.io/@johnkariuki)

(https://hrd.cm/2k90ljr)
23Comments Scotch
1 Login

Recommend 2 Share SortbyBest

Jointhediscussion

Matin2daysago
FirstIwanttothanksforyourgreatandfunctionalarticle,yousavedmytime!
second:isthereanywaytohaveconstraintsonJSONfielditems?
Reply Share

NomanUrRehman>Matin5hoursago
Youarewelcome!

Constraintsasinthedatatypesallowedforanattribute?

Forexample,attributeabcshouldonlyacceptintegervalueswhereas
attributexyzshouldonlyacceptstringvalues?
Reply Share

AlbertRaj13daysago
Excellentman,thereisasmallspellmistake,thoughitsminormistakebettertobe
removed.:)
CREATINGAPRODUCT>3rdparagraph>Moreoever
Reply Share

NomanUrRehman>AlbertRaj5daysago
Thanksalotforpointingthatoutandtheappreciation:)
Reply Share

IvanEliseoTinajeroDiaz14daysago
WooMan,youreallydeserveabeer.Thanksforsharethiswonderfultutorial.
Regards
Reply Share

NomanUrRehman>IvanEliseoTinajeroDiaz5daysago
Youarewelcome:)
Reply Share

RobKumaramonthago
Aren'ttheforeignkeyconstraintsinthecreate_productsmigrationsincorrect?
Shouldn'tdeleteberestrictedandupdatebecascade?
Reply Share

NomanUrRehman>RobKumar20daysago
Thanksforpointingitout.Fixed.
Reply Share

SoftPdfamonthago
WhenItriedtoruntheselinesonphpmyadmin

CREATETABLE`e_store`.`products`(
`id`INTUNSIGNEDNOTNULLAUTO_INCREMENT,
`name`VARCHAR(250)NOTNULL,
`brand_id`INTUNSIGNEDNOTNULL,
`category_id`INTUNSIGNEDNOTNULL,
`attributes`JSONNOTNULL,
PRIMARYKEY(`id`),
INDEX`CATEGORY_ID`(`category_id`ASC),
(https://hrd.cm/2k90ljr)
INDEX`BRAND_ID`(`brand_id`ASC),
CONSTRAINT`brand_id`FOREIGNKEY(`brand_id`)REFERENCES
`e_store`.`brands`(`id`)ONDELETERESTRICTONUPDATECASCADE,
CONSTRAINT`category_id`FOREIGNKEY(`category_id`)REFERENCES
`e_store`.`categories`(`id`)ONDELETERESTRICTONUPDATECASCADE
)

IsawthefollowingError>>
#1064YouhaveanerrorinyourSQLsyntaxcheckthemanualthatcorresponds
toyourMariaDBserverversionfortherightsyntaxtousenear'JSONNOTNULL,
PRIMARYKEY(`id`),
INDEX`CATEGORY_ID`(`category_id`'atline6
Reply Share

NomanUrRehman>SoftPdfamonthago
YouareusingMariaDBwhereasthistutorialiswrittenforMySQL.

IamnotsureifMariaDBsupportsJSONcolumns.
Reply Share

ShahrozeNawaz>NomanUrRehman18daysago
YesMariaDbhasjsonfunctionstousewithcolumnsseethe
completeguideherehttps://mariadb.com/kb/en/m...
Reply Share

NomanUrRehman>ShahrozeNawaz15daysago
YourlinkpointstothedocumentationofJSONfunctionsin
theknowledgebase.

However,IcouldnotfindtheJSONdatatypeinthelisted
datatypesintheknowledgebase.

https://mariadb.com/kb/en/m...

Canyoupointtoaknowledgebaselinkthatclearlymentions
thereisaJSONdatatype?
Reply Share

ZrelliMajdi2monthsago
behindthescenedoesmysqlstoreeachjsonkeyasnewvalueorrepeatedkeywil
bereferenced
Reply Share

NomanUrRehman>ZrelliMajdi2monthsago
Thedocumentationsays:

"Optimizedstorageformat.JSONdocumentsstoredinJSONcolumnsare
convertedtoaninternalformatthatpermitsquickreadaccesstodocument
elements.WhentheserverlatermustreadaJSONvaluestoredinthis
binaryformat,thevalueneednotbeparsedfromatextrepresentation.The
binaryformatisstructuredtoenabletheservertolookupsubobjectsor
nestedvaluesdirectlybykeyorarrayindexwithoutreadingallvalues
beforeoraftertheminthedocument."
Reply Share

MichaelBOUVY2monthsago
ThanksNomanforthisexcellentarticle!

IguessusingJSON_EXTRACTfunctioninaWHEREclausemeansthatevery
singlerowofthetablehastobeprocessedtocheckifitmatches,right?Istherea
waytodefineindexesonJSONpaths?
Reply Share

OlivierDASINI>MichaelBOUVY23daysago
Verygoodarticle,onlytheindexpartismissing:)
YoucanindexJSONcontentwithGeneratedColumns.
Youcanfindmoredetailsinthisblogpost:http://dasini.net/blog/2015...
Reply Share

NomanUrRehman>MichaelBOUVY2monthsago
(https://hrd.cm/2k90ljr)
AsfarasIknow,youcannotindexJSONcolumnsdirectlyinMySQL.

However,thereisaworkaround,sortofavirtualcolumn.

Moredetailscanbefoundathttps://dev.mysql.com/doc/r...
Reply Share

NandaKumar2monthsago
NandaKumar2monthsago
AppreciatedArticle.Wellwritten.
Reply Share

NomanUrRehman>NandaKumar2monthsago
Thanks:)
Reply Share

Feras2monthsago
Howicanupgrademysqlversiononxampp?
Reply Share

NomanUrRehman>Feras2monthsago
It'sabitlongandcomplicatedprocedure.

ThebestadviceIcangiveyouisjustupdateXAMPP.

LastIchecked,theydocyclewithPHP/Apache/MySQLreleases.
Reply Share

Test2monthsago
Verygoodarticle,thanks!
Reply Share

NomanUrRehman>Test2monthsago
Youarewelcome!
Reply Share

Subscribe d AddDisqustoyoursiteAddDisqusAdd Privacy

Subscribe to get our free eBook

BUILD YOUR FIRST NODE.JS APP

Subscribe to the Scotch Newsletter

Get the Free eBook

(https://hrd.cm/2k90ljr)

TheTeam(/about) ThePub(https://pub.scotch.io) OurStuff AboutUs(/about)


(https://digital.scotch.io) ScotchSchool(https://school.scotch.io)

Vous aimerez peut-être aussi