Paul S. Tuon
`~The engine of your inginuity is limited only to your imagination!!!~`
UX Engineer
Minneapolis, MN (US)
Attended: University of
Minnesota (Twin Cities)
Majored: Economics/Computer
Science
Programming:
I am a Software Engineer/Economist-- specializing in all kinds of software applications development.
My field of expertise:
Java, Delphi, C#, Python, PHP, Node.js, JavaScript, jQuery, Ajax, MySQL, PDO, and of course, CSS.
I enjoy programming and it feels like a hobby to me.
It probably falls in both categories of programming and hobbies!!!
Social media:
Love going online and interacting with total strangers on social medias!
It's fun!!
And it's so 21st century and beyond!!!
Hardly a bane on my existence!
Sports:
Enjoy watching/playing soccer, Karate, and the World Cup.
And I was a long time avid season-ticket holder of the Minnesota United Prefessional Soccer Team prior to Covid-19.
Going as far back as I could remember (even being just a child), I have always dreamed of owning my own company and taking it to the public.
It is a lifelong dream that is still with me today!
Hey, I can dream, too!
Can't I?
I can say this:
My will, determination, and resolve are unshaken!!!
Never have been and never will be!!!
search .....
Remember that all other brokerage services charge you when you open your trade and also charge you when you close out your position. That's $10 for just one round trip--a $5 for opening position and a $5 for closing position. That's a lot of $5(s) and $10(s) to waste.
Please check the following out:
tastyworks.comAnother very good brokerage house that has zero commissions, zero options contract fees, zero deposit minimum. Please check the following out:
Webull.COM There are plenty of other brokerage services that have no minimum -- or if they do, it is very little minimum and the majority of them have a minimum of $25. Some brokers have no minimum but require their clients to keep accounts active by mean of trading. So look around.Article Date: August 9, 2014
By Paul S. Tuon
The total of all those shares (or in the previous example, 400,000,000) is called shares outstanding. All those shares outstanding is called a stock, hence answering the question posed earlier 'what is a stock?'
Notice that a company can have many stocks: common stock, preferred stock and warrants, and each of the three types of stocks can contain classes of their own, such as common stock class A, B, C, etc., Preferred stock class A, B, C, etc.; and each class in those three types of stocks is also called a stock.
Now the answer to the question: 'what is a stock?' is now much clearer.
Different classes of a stock contain different rights and privileges, with the highest rights and privileges given to the highest alphabet order. For example, class A shares have higher rights and privileges than class B, class B shares have higher rights and privileges than class C, class C shares have higher rights and privileges than class D, and so forth.Of the three types of stocks, common stock shares have the least rights and privileges and preferred stock shares have the highest rights and privileges and its classes shares generally have preferrential treatment over all common stock classes shares and also have preferrential treatment over all warrant shares of a stock as well. warrant shares generally have rights and privileges somewhere between common stock shares and preferred stock shares.
A share of a stock whether a common stock, a class A, B, or C, or preferred class A, B, or C, or warrants, represents a part-ownership in the company. A publicly traded company is owned by its shareholders, including the original owner(s) -- often thousands of people and institutions -- each owning a fraction of the whole company.A newly formed company usually requires a "bylaw" written by the founders of the company. The bylaw states the rights and duties of the company. At a very minimum, the bylaw should issue certificates of stock ownership to the shareholders involved.
Here is what a typical certificate of ownership looks like:
Certificate Number: 1000 This certifies that Mary Q. Public is the owner and registered holder of twenty thousand (20,000) shares of ABC Corporation, transferable only on the books of the corporation by the holder hereof in person or by duly authorized attorney upon surrender of this certificate properly endorsed. IN WITNESS WHEREOF, the said corporation has caused this certificate to be signed by its duly authorized officers of the corporation this 2nd day of October, 2018. ABC Corporation by president: ___________________________ John J. Doe |
shareholders dilution.
shareholders dilution
: it dilutes existing shareholders' value because there are more shares outstanding and perhaps there are more shareholders in the company. The more shares the company is selling the more dilute value for existing shareholders.Strike | Symbol | Last | Chg % | Bid | Ask | Volume | Open Interest |
$15.00 | T100918C00015000 | 7.45 | 0.23 | 7.40 | 7.50 | 45 | 175 |
$25.00 | T100918C00025000 | 3.45 | 0.04 | 3.40 | 3.50 | 106 | 694 |
Call Options Quotes |
For AT & T, Inc (Symbol: T): 07-30-2010: $25.94 |
Expire at close on Friday September 17, 2010 |
Strike | Symbol | Last | Chg % | Bid | Ask | Volume | Open Interest |
$23.00 | T100918C00023000 | 2.94 | 0.23 | 3.00 | 3.05 | 45 | 175 |
$24.00 | T100918C00024000 | 2.15 | 0.04 | 2.10 | 2.13 | 106 | 694 |
$25.00 | T100918C00025000 | 1.31 | 0.05 | 1.27 | 1.28 | 138 | 2,924 |
$26.00 | T100918C00026000 | 0.63 | 0.00 | 0.60 | 0.61 | 322 | 11,331 |
$27.00 | T100918C00024000 | 0.21 | 0.02 | 0.19 | 0.21 | 466 | 3,637 |
$28.00 | T100918C00024000 | 0.06 | 0.01 | 0.04 | 0.06 | 120 | 808 |
$29.00 | T100918C00029000 | 0.02 | 0.00 | N/A | 0.02 | 10 | 20 |
$30.00 | T100918C00024000 | 2.15 | 0.04 | 2.10 | 2.13 | 106 | 694 |
Put Options Chain Quotes |
For AT & T, Inc (Symbol: T): 07-30-2010: Price $25.94 |
Expire at close on Friday September 17, 2010 |
Strike | Symbol | Last | Chg % | Bid | Ask | Volume | Open Interest |
$23.00 | T100918P00023000 | 0.05 | 0.00 | 0.09 | 0.11 | 6 | 1,651 |
$24.00 | T100918P00024000 | 0.15 | 0.01 | 0.16 | 0.18 | 131 | 1,025 |
$25.00 | T100918P00025000 | 0.31 | 0.00 | 0.32 | 0.34 | 76 | 3,194 |
$26.00 | T100918P00026000 | 0.63 | 0.03 | 0.65 | 0.67 | 283 | 1,634 |
$27.00 | T100918P00027000 | 1.24 | 0.02 | 1.24 | 1.27 | 273 | 1,774 |
$28.00 | T100918P00028000 | 2.05 | 0.03 | 2.09 | 2.11 | 78 | 439 |
$29.00 | T100918P00029000 | 3.15 | 0.15 | 3.05 | 3.10 | 89 | 18 |
$30.00 | T100918P00030000 | 4.15 | 0.15 | 3.95 | 4.10 | 124 | 1 |
In options lingo, selling a "covered call" is called "writing a covered call." There are two steps for this process:
Step 1: Buy the stock for the purpose of selling the right to own the stock to someone else.
Step 2: Sell a call option or writing a call option. Writing a covered call option means that you're giving other investors the "right to buy" your 100 shares of your stock that you'd bought and currently are holding them.
The call option you sold requires you to deliver your 100 shares of the stock if the option is exercised. That can happen anytime between the time you sold and the expiration date of the option. Remember that you need to hold your stock until the option expires.
As of this writing (March 26, 2018), the call option you want to sell is the Citygroup stock quoted for April 27, 2018 (expire in one month) with a strike price of $67.00 for a premium of $3.50 per share. OK, you bought a Citygroup stock at $67 a share and turn around and sell a covered call for the same amount as you bought them.Update: October 27, 2020. Nivdia stock: $536/share.
The stock is now at $536/share (yeh!!!), surpassing my 5-year target of $320 per share. Better yet, this company is growing rapidly in a 'breakneck' speed through in-house inovations and outside acquistions. So the future is very bright. The management is very smart in using their 'skyrocket' high stock price to buy these valuable companies without denting their cash on-hand. That's what you can do when your company's stock is as high as NVIDIA is - it gives you leverage and power to do things that otherwise would not be possible.
Nvidia reminds me of Amazon just a few years ago when Amazon stock was already trading around $500 per share and the stock was moving up steadily ever since [February 26, 2016 at $555 per share; October 27, 2017 at $1,100 per share; May 11, 2018 at $1,603 per share; November 11, 2019 at $1739 per share; March 27, 2020 at $1,900 per share; May 29, 2020 at $2442 per share; September 4, 2020 at $3294 per share].
Let me clarify my view on this comparison: Nvidia is not Amazon nor will it perform like Amazon stock in the future. It will never be anything near what Amazon has done -- no stock is nor will be. However, the strategy that Nvidia employs recently resemblances the strategy that Amazon employed leading up to their current high performances of its stock.
The purchase of ARM is a very smart move by Nvidia's management and it will do a lot of good for the future of this company. Will its stock performs like Amazon's stock in the future? We'll see! And time will tell!
Here is the synopsis from the press release:
Unites NVIDIA's leadership in artificial intelligence with Arm's vast computing ecosystem to drive innovation for all customers
NVIDIA will expand Arm's R&D presence in Cambridge, UK, by establishing a world-class AI research and education center, and building an Arm/NVIDIA-powered AI supercomputer for groundbreaking research
NVIDIA will continue Arm's open-licensing model and customer neutrality and expand Arm's IP licensing portfolio with NVIDIA technology
Immediately accretive to NVIDIA's non-GAAP gross margin and EPS
Consideration of $40 billion to be met through a combination of NVIDIA shares and cash
Please see
NVIDIA to Acquire Arm for $40 Billion, Creating World's Premier Computing Company for the Age of AIHere is my definition of "dollar cost average":
"Stocks rarely go up in a straight line."
Just remember that definition when you think of a dollar cost average.
Because of the nature of stocks, which rarely go up in a straight line, it makes a great strategy for a long term investment.
I'm not the only one who believe that this stock is going to go up in five years. Here is what WallStreet analysts are saying about Nvidia:Goldman said it remains "Buy-rated on the stock as our view that Nvidia has access to one of the best growth opportunity sets in Semis and that it has a sustainable competitive lead within remains unchanged."
"The stock will likely not bounce back right away, given the severity of the miss," Morgan Stanley said.
Wells Fargo Analyst: Concerns (and now frustration) over a significant gaming channel inventory burn-off have materialized ... While we can appreciate that NVIDIA's weak F4Q19 outlook is impacted by a 1-2 quarter work-down of Pascal mid-range gaming card inventory in the channel ($600M; assuming no sell-in in F4Q19 as crypto-related dynamics flush through the channel), couple with a seasonal decline in game console builds, we think investors will be frustrated by NVIDIA's comments exiting F2Q19 that: "...we [NVIDIA] see inventory at the lower-ends of our stack...inventory is well positioned for back-to-school and building season that's coming up on F3Q19..." Bottom Line: Well, even if we model a strong double-digit growth in DCG next year, we think there is a high likelihood that NVIDIA will not grow next year. We are modeling for as such. The large shortfall in guidance due to a bloated channel due to crypto-currency is in sharp contrast to the comments around channel inventory from the company at the last earnings call. Our estimates and target price are going lower. We remain Market Perform rated. We are Buyers on weakness.
SunTrust Analyst: The surprisingly weak Q4 guide appears temporary. NVDA guided Q4 20% below consensus revs as the company halts 1/3 of gaming segment sales to flush channel inventory built during the crypto enthusiasm in 1H18. This badly damages near-term revenue and profits, but Datacenter, Pro-Viz, and Automotive results support our structural growth view. Gaming resets our 2019 & 2020 EPS to $7.33 & $8.70 (from $8.18 & $9.59). PT goes to $237 (from $316) based on 30x (17x discount to rapid-growth tech peers) our CY20 EPS, discounted back 1 year. Buy.
RBC Analyst: Going forward, we think the focus will now shift to Data Center as gaming expectations are now reset due to crypto currencies and a product transition (Turing) which will unlikely ramp until around the Jul-qtr time frame. Net Net: we lower our price target due to the lower than expected results (PT to $260 from $310). Positively, gaming and Pro Visualization will likely be up q/q in January helping gross margins and offsetting the material gaming weakness.
Payment Type | Declared Date | Payable Date | Amount |
Annual Regular Dividend | February 25, 2016 | March 16, 2016 | $.31 |
Annual Regular Dividend | February 21, 2017 | March 9, 2017 | $.35 |
One-time Special Dividend | February 21, 2017 | March 9, 2017 | $1.00 |
Annual Regular Dividend | February 21, 2018 | March 16, 2018 | $1.05 |
One-time Special Dividend | February 21, 2018 | March 16, 2018 | $3.00 |
Annual Regular Dividend | February 25, 2019 | March 15, 2019 | $1.75 |
One-time Special Dividend | February 25, 2019 | March 15, 2019 | $4.25 |
Annual Regular Dividend | February 24, 2020 | March 16, 2020 | $16.00 |
A foreign reserve is the foreign currency that a country has in its possession or in its bank vault. Remember that a country typically has its own currency, e.g., the United States has the dollar as its own currency, Great Britain has its own currency called the Pound, China has its own currency called the Yuan, Japan has its own currency called the Yen, the 12 European countries: France, Germany, Italy, etc., have their own currency called the Euro dollar.
For the most part, each currency can be used inside its own country only; for example, the Chinese Yuan can be used only inside China, and likewise, the European Euro dollar can be used only inside the 12 European countries and nowhere else.
When people travel to a foreign country, they have to exchange their own country's currency with of that foreign country's currency.
For example, if you go to China, once you arrived at the Chinese airport you need to change your U.S. dollar with the Chinese Yuan so that you can use it to buy things while you're in China. When you go to France (or any one of the 12 European countries that carry the Euro dollar), you need to exchange your U.S. dollar with the Euro dollar so that you can use it to buy things in those countries.
Likewise, when businesses invest or trade with a foreign country, they have to exchange their own country's currency with of that foreign country's currency.
For example, when Walmart Corporation buys Chinese products to sell in their stores in the U.S., they need to exchange their U.S. dollar with the Chinese Yuan so that they can use the Chinese Yuan to buy those Chinese products because the Chinese government barred the use of foreign currencies inside China.
Most countries do this as well, e.g., you can't use the Euro dollar to buy things in the United States either.
This exchanging of currencies is called the foreign exchange market.
Trades are the main source of the foreign exchange market (i.e., Walmart buying Chinese goods), causing each country's currency to fluctuate (or rise/fall in value) according to the supply and demand of the currency.
For example, the U.S. dollar is typically in high demand by traders all over the world and therefore it is more valuable than other currencies.
Keep the supply/demand principle in mind when you deal with the foreign exchange market, because it is based on the supply and demand of the currencies involved in the trade or exchange.
This trading of currencies in the foreign exchange market is where countries are so worried/abcessed with the concept of foreign reserve--they have to!. Their economy depends on it!
Now we're on to the description of the foreign reserve concept.
I'm little lazy, so I'm going to refer you to some excellent tutorials on the Web, which can explain better than I can.
As you watch the following videos, keep the trading of currencies in the foreign exchange market in mind because it is all about trading of currencies.
Also, don't forget to keep the supply/demand principle in mind as well.
To understand the concept of foreign reserve, you have to at least finished watching the third video in the list below. The first two videos are just the introduction to warm you up for the concept of the foreign reserve. Here are the video tutorials:
|
Tesla can issue more stock to sell to the public and use that cash to pay off the bondholders. But having stock prices higher benefit Tesla because Tesla can sell less shares to earn more cash. On top of that, if Tesla's stock is higher than$359.87 Tesla doesn't have to issue more shares to sell -- they can just elect to convert the bonds into shares of Tesla's stock.
So having Tesla's stock stay high has many benefits to Tesla and that's why Wall Street was speculating that Musk's motive was to drive up Tesla's stock when he tweeted about taking Tesla private.
Now in about two years later, Tesla's stock was trading above $2,000 in July and in much of the early August of 2020, making the convertible bonds talk above a moot point or non-issue.
In other words, Tesla and Elan Musk won the battle against critics particularly short sellers who bet against him and his company and lost their shirts to the tune of $38 billions in 2020 alone.
And my gosh, Elan Musk won big against his critics and at the same time propelled himself to the tune of being the richest people on earth (worth $194.8 billion as of January 7, 2021), beating Jeff Bezos ($185.8 billion) of Amazon for the top spot.
Update: August 12, 2020. Tesla stock came down to earth to: $1,374/share after Tesla's stock price climbed above $2,000 recently.
On August 12, 2020, Tesla announced a five-for-one stock split set to take effect at the end of August 2020 after Tesla's stock price climbed above $2,000 recently.
Every Tesla shareholder will receive four additional shares for every share they currently own when trading ends on August 28, 2020, the company said in a press release. The value of all five shares will equal the stock's pre-split closing price from that same day.
Trading of Tesla shares on a split-adjusted basis will begin on August 31, 2020, and is expected to be right around of Tuesday's (August 11 2020) closing level, in which the newly split shares would be worth right around roughly $274 each. The split alone won't change Tesla's market cap. Yet cutting the barrier to entry for smaller investors to buy in could boost Tesla's share price.
Update: December 31, 2020. Tesla stock: $706/share up from the post split of $274 a share on August 28, 2020.
So everything with yield curve has to do with bond yields -- and bond yields have to do with the economics principle supply and demand.
The higher the bond yield, the lower the demand for that bond. Likewise, the lower the bond yield, the higher the demand for that bond.
Say what? The higher the bond yield, the lower the demand for that bond? Does it make any sense?
Take it this way: When you see stores with advertisement that says something like 30% off, 40% off, 50% off, or 60% off, they're telling you that their products are not in high demand and to get rid of those products, they have to lower prices to entice customers to buy them.
Bonds work the same way: When there are lack of demand for the bonds, their yields are typically higher because seller(s) of those bonds will offer bond buyers with higher interest rates to entice bond buyers to buy those bonds; and therefore, making those bonds having higher yields. Make sense?
So the yield curve is the graph that plotted the bond yields. Economists use charts and graphs to interpret the activities of the economy and bond yields is a very important key that drives economic activities.
In the graph illustrated below shows the yield curve for the 10-year bonds, and it is not upward slopping, but rather, it is flattening, which means that the demand for 10-year bonds are in high demand, driving their yields down, hence the flattening of the yield curve. In other words, people are buying more 10-year bonds than they're buying 2-year bonds.
The bond market is a great predictor of future economic activity and future levels of inflation, both of which directly affect the price of everything from stocks and real estate to household items.trending toward zero
, or flat. See the graph below:The horizontal line that has number 0 (zero) can be viewed as the benchmark 2-year bond yield (for easier interpretation). It is actually a line representing maturity dates, however. A 10-year bond is plotted against this horizontal zero-line with varying maturity periods.
If the plotted graph representing a 10-bond goes below zero -- an "inversion" in which the yield on the two-year bond would be greater than the 10-year -- that traditionally signals something is very wrong in the market.If you ever wanted to learn how to program computer programs, particularly learning how to build a website of your own, this tutorial helps you get started and points you in the right direction to achieving your programming goal. This tutorial is not meant to teach you everything about how to program, but rather, a 'get started' guide that guides you in the right direction to help you get started.
For a complete and specific area of programming, such as a particular language you are interested in learning, please check out tutorials on the Web by Googling it. There are lots of free tutorials on the Internet, particularly YouTube.com and the HTML as noted in the following.
A good place to get started is the W3Schools
And here is another good place to get started:
Learn How to Code OnlineAnd here is a forum for the above site where you can ask the experts on programming topics:
Learn How to Code Online: Codecall Programming Forums!As listed in the W3Schools mentioned above, you need to start with HTML and CSS first, and then proceed to server-side languages such as PHP and then to the client-side languages such as Javascript, and then you should learn databases as well, such as PDO and MySQL, and then to specialized languages such as jQuery and Ajax, in that order. So the order you should follow is: HTML, CSS, PHP, Javascript, PDO, MySQL, jQuery, Ajax.
If you have time, you should learn DOM as well. For an introductory course on DOM, see chapter 3 to 7 of my Ajax book called Introduction to Ajax.
If you mastered all the languages mentioned above, you should be able to build any sophisticated Web applications easily. After that, if you want to learn other languages as well, then you should learn those languages listed in the W3Schools mentioned above in no particular preferential order guideline.
W3Schools above listed category under Javascript, which includes Node.JS and other excellent server-side languages as well, but you really only need to learn PHP is enough for a while. PHP is the most popular server-side language out there, but Node.JS is getting more popular as it is very good in streaming applications, such as movie shows and other live streaming applications.
However, you can accomplish the same thing using PHP, but it is easier to program streaming applications using Node.JS than PHP as Node.JS is specifically built for streaming applications.
If you want to learn how to program sophisticated desktop applications, start with Java, and then C++, and then either Python or C# (pronounce 'see sharp') or even Delphi if you dear to venture into the deep end of the programming language world. But the first three or four listed above is sufficient and you can accomplish any sophisticated desktop applications just fine.
If you just want to learn only one desktop language, Java is a very good choice to learn.
If you dear to venture into the deep end of the programming language world for desktop, here is a link to an excellent language called Delphi
If W3Schools doesn't have the topics I mentioned here, just Google around and you'll get plenty of results for you to get started. Have fun learning!
Here are the steps on how to get started programming for beginners:
First, you need an editor to write your programs with. There are lots of free editors on the Web such as NetBeans IDE, a free, open-source Integrated Development Environment for software developers, particularly for desktop applications. You get all the tools you need to create professional desktop, enterprise, web, and mobile applications with the Java language, C/C++, and even dynamic languages such as PHP, JavaScript, Node.JS, Groovy, and Ruby.
NetBeans IDE is easy to install and use straight out of the box and runs on many platforms including Windows, Linux, Mac OS X and Solaris.
So if you are interested in learning to program desktop applications and as well as Web applications, NetBeans IDE, unlike many other editors mentioned below, is suiteable for both applications.
Other text editors that are very popular among beginners are Notepad++, Sublime Text, Atom, Ultra Edit, TextMate, BBedit, MAX's HTML Beauty++, etc. Please Google them to learn more about them. Or you can just Google the term 'free text editors' and you'll get a bunch of results.
Personally, I have been using two text editors simultaneously: one is NetBeans IDE because I need to compile and run programs written in Java for desktop applications and another is MAX's HTML Beauty++ for doing non-desktop applications for the Web, such as Javascript, Node.JS, HTML, CSS, etc. MAX's HTML Beauty++ is perfectly suitable for these Web languages.
As noted above, MAX's HTML Beauty++ is only suiteable for building Web applications and NetBeans IDE is suiteable for both desktop and Web applications.
What I like about MAX's HTML Beauty++ old version is that it color-codes all PHP code in yellow and leaving all other programming languages code as a default color, which is a non-color black and white.
Using MAX's HTML Beauty++ old version, you can preview your webpages instantly while you're still building it by switching back and forth between a "preview" and an "edit" mode. This is a great feature for beginners trying to learn how to program Web applications.
If you are not into building sophisticated desktop applications, here is MAX's HTML Beauty++ download that will do the job just fine for building Web applications.
The download above is an older version, which happens to be my favorite version that I am still using it to this day, and I prefer this older version over the newer version, which is a 2004 version. If you prefer the newer 2004 version, here it is: http://www.htmlbeauty.com/bsetup.exe download
As a matter of fact, any text editor, including Microsoft NotePad that comes with your Windows operating system, will do just fine for building Web applications.
Also all these downloaded text editors come inside an archive compression zip file. You need to extract them once you've downloaded them using any archive unzip application. There are lots of free archive zip applications available on the Internet. See the following.
Once you've downloaded your favorite text editor, including my favorite text editor MAX's HTML Beauty++, extract it using free zip extracting applications like WinZip Express Zip WinRAR or WinRAR here! PeaZip
The archive zip application is a compression program that compresses the content into a small version of the original plain text content so that it can be sent over the Web easily and faster. It compresses the content and decompresses (or extracts) that same content once you extract it. Think of the archive zip program as a plastic zip bag that you put food in it and then seal it to protect the food from spoiling.
Once you've downloaded your favorite archive zip application, you need to install it as you normally would with any other applications by following the installation instruction. It shouldn't be that hard to install the archive zip application. You can install it in any directory of your choosing and it doesn't need to be in a particular directory at all.
Just make sure that you say "yes" when it prompts (you) if you want the installation program to create an icon in the desktop for that particular archive zip application. If you said "yes," it will create an icon for that archive zip application and it will put that icon on your desktop pane. Self-explanatory!
Actually, you don't even need to have the icon shown on your desktop pane unless you need to open it to create an archive zip application to put your files in to send your files to the server. In that case, you definitely need to have an icon shown on your desktop pane.
So basically, after you'd installed your favorite archive zip on your laptop/desktop you can use it to extract your downloaded text editor that came inside the zip archive by clicking on your "raw zipped" downloaded favorite text editor.
Remember that all downloaded applications come inside an archive compression zip application -- it is totally zipped or compressed. So you need to extract/uncompress the downloaded text editor, which came inside the archive compression zip application.
Just clicking on the "raw zipped" downloaded text editor in raw format and it will open up (automatically) the archive zip application that you had installed on your computer. You see, this is why you don't need to create an icon on your computer pane because you don't need to click it to open it. It opens the archive zip application automatically every time you click on the "raw zipped" downloaded application.
Say you just downloaded a text editor called MAX's HTML Beauty++ and all you have to do is double click on that downloaded apllication and it will automatically open up your favorite zip archive application and extract your downloaded text editor for you without you having to find your zip archive application icon to double it and open it. It opens automatically for you once you double click on the downdloaded text editor.
Once it opens up the archive zip application it should show that your text editor is inside the archive zip application. In that archive zip screen, it shows a lot of options you can do, such as "create archive" for creating archive zip application packages, and "extract" option, which is to extract the (current) downloaded application. Follow the on-screen instruction and you'll be fine! It is very easy to use archive zip applications.If for some reasons you need to send files to the server, you can open the archive zip application by just clicking on the icon shown on your computer pane and it will open the archive zip application for you to use. This is why you need to allow the installation program to create an icon on your computer pane so that you can open it and use it easily.
Let's say you have some photos, or any other content for that matter, and you want to send them to a remote server, you can put those photos/content/files in an archive zip application and send them to your remote server or any server you have accessed to. And then create a link to that archive zip file name and your users will be able to download those content from your website.
Once your users downloaded the photo content they can decompress (or extract) that photo content from the archive zip application to be viewed at their own leisure.
For example, say you have a bunch of photos and you want to create an archive zip application by opening the archive zip application and then clicking on "create archive" or for some archive applications just say "create", and it will open a screen to allow you to create the archive zip application. From there, just follow the on-screen instructions and you'll be fine.
Among the instructions is that it asks for a file name for the archive zip application you're creating; for example, you can name it as "myphoto" without any extension and it will create an empty archive zip application without any content in it.
From there, you can put your photos/content inside that newly created archive zip application by copy and paste them or if the photos/content/files are on the computer pane, you can drag and drop them easily. It is very easy to create and move content into the archive zip applications.
Now you have your photos/content/files inside your newly created archive zip application with a file name for that archive zip application and ready to go. Next, you can upload the entire newly created archive zip application to your server so that your users can download them.
To allow your users to download them, you need to create a link to that particular archive zip application that you just uploaded to your server. For example, say you upload your archive zip application to your website, which has a directory called "download," you can create a link somewhere on your website page like this: <a href="http://www.mywebsite.com
/download/myphoto.zip">
download my photos!</a>
. That is it!
Pay special attention to the extension, which in the above case, it is a ".zip
" extension. So you need to specify the exact extension in order for it to work. Different archive compression applications have different extensions and they are named accordingly in a variety of extensions, i.e., .zip
, .ar
, .rar
, .pea
, etc. Check your particular archive compression applications for the extension they use.
The process just described is how you allow your users to download anything from your website -- the same sort of thing you see other websites allow their users to download some content from their websites.
Well, the first step is a little too lengthy than I would have liked but I just wanted to be very clear and precise to help you along!
Next, you'll need a local webhost to build and test your applications offline -- that is, you're using a fake web server to build and test your web applications offline on your computer without having to rent a live "real" web server. Once you've built and tested your web applications offline, you can decide to get a real web server to host your web applications online so that your website can be viewed by people all over the world.
As a matter of fact, most experienced programmers, including myself, use "fake" server to build and test applications on a daily basis. So I strongly recommend beginning programmers to do the same and use localhost to build and test your web applications. Once you finished building and testing your applications and then you can find a real web server to host your websites. Google around using phrases like this: "free webhosting services" to find a real web hosting service provider to host your websites. There are lots of them out there.
Check out my other tutorial at the bottom of this page titled: 'Migrating your website to a real live server' for a free web hosting service provider that I found on the Internet when I Googled around using phrases like this: "free web hosting services".
That free web hosting service provider that I found is one of the best free web hostings out there. I used that free web hosting to host one of my websites as well. You, too, can signup for a free web hosting account with them and use it to host your website just like I do.
Please DO NOT use free web hosting to build and test your web applications because it slows down other people using the same host. All free web hostings are shared hosting: meaning all users of the shared hosting are routed through the same bandwidth and if lots of people use their live hosting to build and test their web applications, it slows down the shared hosting traffic.
So please use your localhost to build and test your web applications.To get a "fake" web server, usually called localhost, you can search the web using a term like "localhost webserver", or you can Google a specific term like "WAMP server", "XAMPP server", "MAMP server", "VAGRANT server", or DOCKER.i.
Once you've identified which one you want, go ahead and download and then install it on your local machine, preferably on your laptop/desktop. You can choose to install it in any location on your desktop/laptop and it doesn't matter; however, for ease of use, choose the default setting shown on the installation prompts.
Once you've installed your localhost web server, you're ready to build and test your web applications just like if you had rented a real live web server from a hosting vendor. The only difference is that your "fake" web server is locally run and is not visible on the web like a real web server does. Most of the instructions on the web are self-explanatory and are very easy to follow even for beginners who never know how to program a single program. You can check out Youtube.com on tutorials on these topics as well.
Once you've installed a WAMP local host web server, all the required applications, such as the Apache (web server), MySQL (database), PHP programming language, and as well as the PHPmyAdmin (a MySQL application), are all bundled and installed completely into your local laptop/desktop to work with each other seamlessly.
In WAMP, you can work with databases using MySQL to store and retrieve data, as well as using PHP programming language to program your web applications. WAMP is not restricted to just PHP, however -- you can use other languages as well.
WAMP is a popular alternative of XAMPP for Windows. However, you can use XAMPP as well and it doesn't take much time to install XAMPP either. But developers may prefer to use WAMP since it is specifically crafted for Windows only -- unlike, XAMPP, which can be used for Linux and Mac OS as well.
However, both platforms are equally stable and provide the same functionality.
So you can choose any platform amongst the two to fulfill your objective. But all those who are searching for guidance on how to install WAMP on Windows system should follow the below-given steps. So let's get going!!
How to Install WAMP on Windows
Download the WAMP Server: Wampserver 64 bit x64
You want to choose a 64 bit version. The 32 bit is for older computers or laptops, which is outdated in today's programming world. If you're using computers that is still using a 32 bit, by all mean choose 32 bit version. To check what version your computer is running on, go to the status bar at the lower left corner of your computer screen and type in the search box: control panel and press enter.
The "Control Panel" screen should pop up. In that screen, look for a section called "System and Security" or "System and Maintenance" or anything that has a word "System" on it. For Windows 7, 8, 10, it should says "System and Security." Click on that topic and a "System and Security" screen should pop up.
Next, look for the topic "System" and click on that topic and a "System" screen should pop up. In that screen under the "System" section it lists the "System type" which should say a "64-bit Operating System or 32-bit Operating System, depending on your computer. If it says "64-bit Operating System, your computer is running on a 64-bit operating system. "32-bit Operating System", otherwise.
Initiate WAMP Server Installation Process. I'm being lazy and for the rest of the installation instructions, I will refer to an excellent instruction on the web: here it is: click here!
In that instruction, be careful in step 2. WAMP server looks for a version of Microsoft Visual C++ re-distributable package already installed on your laptop/desktop. Most of the laptops/desktops come with a Microsoft VC++ re-distributable package already pre-installed, so you don't have to do anything. However, for some odd reasons, some laptops/desktops came without that Microsoft Visual C++ re-distributable package pre-installed.
In that case, you might have to search the web for "Microsoft Visual C++ re-distributable package" and download it and install it using default settings contains in its installation application. When you install Microsoft Visual C++, it is very easy and self-explanatory, the same way you install a WAMP server -- they both are self-explanatory, allowing you to just use default settings.
FYI: If you look in the "Control Panel" screen mentioned earlier, it should shows Microsoft Visual C++ installed already; and in that case, WAMP server will find it and use it to complete the installation process, and thus, you don't need to do anything on your part, sparring you from having to search the web.
Once you get through the Microsoft Visual C++ re-distributable package installation process and proceeds to the end of the installation process, the last thing the WAMP server installation guide will prompt you to do is, to enter/choose a text editor. You can accept a default text editor in the prompt or choose your favorite text editor to use with your newly installed WAMP server. It looks something like this:
It's okay one way or another as it is not very significant if you do not choose a particular text editor or not as a default text editor for the WAMP server to use. It won't effect/harm your WAMP server at all.
However, I strongly recommend you just select a text editor of your choice or just leave it as a default text editor that the WAMP server chooses, which is a Microsoft notepad. In other words, by choosing a particular text editor doesn't restrict you from using other text editors with your WAMP server.
It also will prompt you to enter/choose a default web browser to use with your newly installed WAMP server. Likewise, by choosing a particular web browser doesn't restrict you from using other web browser with your WAMP server either. So it looks something like this:
Once you've finished the installation process, you can use the "fake" web server to build and test your web applications offline as you normally would with a "live" real web server. To start, click on the arrow or status icon usually on the lower right corner of your laptop/desktop screen to activate the tap that shows the "fake" web server options listing.
Note: From time to time, if you're using Windows operating system, Windows operating system usually runs updates to update its software drivers and the rest of its system files automatically and periodically. If you're using Windows OS, you may have experienced this update many times already and it's kind of annoying as well, but it's a necessary task for Windows OS, according to Microsoft.
One of the annoying things that this update causes is that it causes the WAMP server to not function properly once the update is completed.
If you experienced this and having issues with your WAMP server to not function properly, just un-install your WAMP server completely from your system and then re-install it again and it should work properly.
Yes, it is very annoying having to un-install and re-install your WAMP server every time a Windows operating system runs its update.
Make sure that you move all of your "projects" in the "www" directory to a different location (or directory) before un-installing your WAMP server; because if you don't, it will delete all of your projects in the "www" directory.
Let's continue on:
It should show an icon that looks something like below with a status icon that usually appears on the lower right corner of your laptop/desktop screen, but with a particular color on it. A green color (as shown below) signifies as the wampserver is ready to use; a grey or pink color, it is not activated; a yellow, it is partially ready and in the process of being ready as it is finishing the loading process.
If it is inactive, all you have to do to fire up your wampserver is to double click on the default icon on your laptop pane that looks something like below:
Usually, when you turn off your laptop, WAMP server is also turned off and no longer active and the green status icon you see above is not shown. When it is turned off, the status icon that usually appears on the lower right corner of your laptop/desktop screen doesn't show the WAMP server icon because it is not activated.
To activate it or turn on your WAMP server, double click on the default icon on your laptop pane to get it activated.
Once your "fake" server is up and running, you can do pretty much just about anything you do with a "live" server. You can click on the arrow next to the green status icon to reveal other options, such as a PHP icon to see what version of PHP is installed on your "fake" server; as well as clicking on PHPmyAdmin to work with database.
Note that PHPmyAdmin in your "fake" server doesn't require you to enter a password, although you can if you want -- but why bother to complicate yourself in having to enter a password every time you try to access your PHPmyAdmin? So just enter 'root' for the username and don't enter a password on the password field. Leave it blank as it is!
Just click "Go" without entering a password and it will open the PHPmyAdmin panel for you.
In the PHPmyAdmin, you can create databases and tables and do pretty much just about anything about database programming.
As stated above, when a localhost is up and running the status icon usually appears on the lower right corner of your laptop/desktop screen. Click on the arrow to reveal the the localhost options. In this option window, you can find a lot of options to choose from, such as PHPmyAdmin, just to name one.
You can click on the particular option to work with it. For example, among the options there is a "localhost" option. Click on that "localhost" option and it will open up a screen that looks something like the following:
As you can see, it shows the configuration status of the localhost such as what version of various entities: Apache, PHP, MySQL, etc. Most of them are really not useful for beginners. Experienced programmers can make use some of these configurations.
The diagram above combines with the one listed below is what it should looks like inside a real server. This localhost web server mimmicks what a real server looks like but on an offline mode.
The localhost also contains a section in the lower half that lists content that is more relevant to beginning users of Wampserver, such as tools and your actual projects that you had created. For example, below it lists three projects that I've created: advanced, framework, noon2noon.com:
If you click on one of the projects it will execute/load the project. For example, if I click on the project called noon2noon.com
it will load and display my website called noon2noon.com
.
However, you can load your website on the browser's url bar as well, the same way you normally would with your regular "live" server. That is the typical usage of localhost: you don't need to load your website through localhost option window, but instead, through a normal loading process in the browser's url bar.
You should try to create a very simple website and click on it in the project section to see what it looks like on your "fake" server. When you create your projects, place them in a directory where you installed your Wampserver. For example, in my case, I installed my Wampserver in a directory that looks like the following:
As you can see, my root directory is called "Desktop" followed by a directory that I named it as "wamp64" followed by a directory called "www." This directory called "www" is created automatically by the installation, so you really don't have to create it yourself. The only directory that you need to create and specify during the Wampserver installation is the "wamp64" part or whatever name you choose. I chose to name it "wamp64."
Any projects you build have to be placed inside the "www" directory in order to be visible by your localhost. For example, in my case, I placed my projects in that "www" directory and inside my project noon2noon.com
it contains content that looks like the following:
One particular content worths mentioning is the index.php file. This is the main starting script file that the server/localhost calls first thing when you try to load the website by typing in your url bar like http://www.noon2noon.com
. However, that is for your real live web server when you migrate your website to a real web server.
But for this tutorial, you're using a fake server called localhost; and therefore, you have to type in the browser bar using localhost instead of www.
So you can simply replace the domain specification 'www' with 'localhost' and just type the name of the folder following it as, in my case, http:
//localhost/noon2noon.com
or simply just localhost/noon2noon.com
and it will load the website automatically.
For my project advanced, which its inside content looks similar to my other two projects framework and noon2noon.com, I can just do the same like this http:
//localhost/advanced
, and likewise for the other one http:
//localhost/framework
, and both websites will load automatically.
Notice that you can include an index.php
or index.html
file as well since it doesn't require you to specify an extension of either a .php
or a .html
and it will work just fine. For examples: http:
//localhost/noon2noon.com
/index
, http:
//localhost/advanced
/index
, http:
//localhost/framework
/index
, and all websites will load automatically.
Please note that when you migrate your websites to a real web server, you have to abide by your web hosting's rule, which tells you what kind of an extension of either a .php
or an .html
that their server is using. If they're using a .php
extension, you'll have to rename your index
file with that extension. Likewise, if they're using an .html
extension, you'll have to rename your index
file extension as such.
For a localhost
, it doesn't matter. It will read from either .php
extension or .html
file extension.
For starter, in your case, just create an index.php
or index.html
file and throw it in a folder and place that folder inside the "www
" directory and type http:
//localhost/ follows by your folder name in the url browser bar to see your website comes alive. Try it!
If your website doesn't come alive and showing a weird screen that looks like the following, it means that for some reason the localhost cannot read your index file:
As you can see, there is no index file listed in the main folder. I deleted it on purpose!
Remember that each website has to have only one index file as a main starting application file. So make sure that you have a functional index file and it has to be only one index file. No index.php and index.html at the same location vying as the main starting application file.
Once you are finished building and testing, you can migrate your projects to your live real web hosting server. For example, in my case, I just take the folder containing the particular project, i.e., noon2noon.com folder, and upload the entire folder to my real live server. That's how you get started in developing website applications.
For starter, you can create a folder and name it and then create an index.php
or index.html
file as well as other files/folders and put them inside that folder that you just created which contains other files/folders as well and upload the entire folder using FileZilla. See my other tutorial on how to use FileZilla.
That is it! Very simple to have your own "fake" server. And from here, the possiblities are endless! Have fun programming!
For beginners, building a website is a daunting task, even for very simple websites that don't have ordinary bells and whistles and are still very challenging to say the least. Fortunately, the folks at the W3Schools.com provide all sort of examples and ready-made web site templates to help beginners get started.
Let's take a look at one template and illustrate how you (beginners) can build your own web site using the ready-made template and customize it to suite your taste.
First go to https://www.w3schools.com/w3css/w3css_downloads.asp and download the css definition (or file) and place it in a folder called css. The default file name is w3.css. You can rename the css file if you like, say css.css or style.css. If you do, don't forget to change the css file name accordingly in your index.php file at the css area at the top of the index.php file to reflect the change in the css file name.
Next, in the same page where you're downloading the css, look on the left side under the category name Examples and try to find a topic name called W3.CSS Templates. Or you can go to https://www.w3schools.com/w3css/w3css_templates.asp
You can scroll down to see the various templates available to use. Pick one and go from there!
If the templates mentioned in the above link is not enough for your tastes, you can find more templates to use right here!
Once you decided which one you want to use, go ahead and click on the "Try it Yourself" button to see the actual code.
Next, copy the actual code, character by character, without missing any character. In other words, no typos in your part or else your web site won't look as intended. If your web site doesn't look like it is intended, try to go back and see if you had any typos in your copied code.
The folks at W3Schools.com used some sort of techniques, such as disabling the "hot link" ability, to disable the copy and paste ability from the web browser. So you can't actually use your web browser to copy and paste the code shown in the templates. You'll have to use advanced editors or tools to copy and paste the code in the templates.
For beginners, advanced tools are out of reach, so just try to copy it manually by hand character by character until you completely copied everything in the template. Yes, it is a pain, but that is what you have to do to learn. Name that template as either index.php or index.html. This is your main index file -- or your main web site file.
Once you have the css file downloaded as well as the template copied and name it as either index.php or index.html, then you need to create a main folder as well as a css folder.
Next, create another folder called image and put all the images/photos that you want to use in your website in that image folder.
You can name them whatever names you like for any folders you create, i.e., MyWebsite, MyFirstProject (for the main folder), css, style (for the css folder), image (for the image folder), etc.
You need to put the index.php or index.html as well as the css folder and the image folder in the main folder. The css file containing the css definitions should be inside the css folder, while the image folder contains all images you need to use. Self-explanatory!.
So your main folder contains everything you need. So you need to put everything in this main folder, including other folders as well such as css, image, etc. The index file should be among the css and image folders as peers at the same level.
That's all you need for this simple website. Three folders: main folder (i.e., MyWebsite or MyFirstProject, or whatever), css folder, and image folder. Plus the index.php/index.html and all three are peers -- meaning they are at the same level in directory. For example:
Of course, you can have more folders and other contents as well as your website gets sophisticated, but for this simple website the three items are all you need for now.
As you can see, I put my main folder called MyWebSite inside the www localhost folder for building and testing web applications. The index.php file contains the content listed below and the actual rendering page content is shown in the following.
Let's see one particular template called "Social Media Template" taken from W3Schools.com website in the W3.CSS Templates category, but I customized it slightly. Here it is:
Here is the actual code along with the commented out code that contained in the original template shown in the W3Schools.com:
File: index.php
<!-- all HTML document start with a !doctype -->
<!-- it is a Document Type declaration to tell the web browser of -->
<!-- what version of the HTML markup language in which a web page -->
<!-- is written. -->
<!-- every time a browser reads a document such as an HTML document it -->
<!-- needs to know what version the HTML markup language is written in -->
<!-- so that it can parse it correctly. -->
<!DOCTYPE html>
<html>
<head>
<title>Template</title>
<!-- a meta (<meta>) tag provides metadata information about -->
<!-- the HTML document. -->
<!-- a metadata information will not be displayed on the page, -->
<!-- but will be machine/browser parsable. -->
<!-- metadata elements are typically used to specify page description, -->
<!-- keywords, author of the document, last modified, and other metadata. -->
<!-- you put metadata in <meta> tags-->
<!-- meta (<meta>) tags are documents for the browsers to read and -->
<!-- used the meta content, for example, you can specify a view port -->
<!-- device dimension such as width. -->
<!-- the word "meta" means self or itself, referring to itself or -->
<!-- a self-referential. -->
<!-- so a self-referential. -->
<!-- meta tags can contain attributes, i.e., name and content. -->
<!-- the two most frequently used in a meta tag are name and content -->
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- the following link is the css link stored in folder named css -->
<link rel="stylesheet" href="./css/mobile.css">
<!-- the following two links were broken down to fit the screen display -->
<!-- these two links are specialized css stored in cloudflare.com -->
<!-- you only need to incude these links if you use awesome fonds and -->
<!-- bootsrap code like form input boxes, textarea, and dialog boxes -->
<!-- you can check out bootstrap tutorials on W3Schools as well! -->
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/
css/font-awesome.min.css">
<link rel="stylesheet"
href="http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/
3.2.0/css/bootstrap.min.css">
<!-- the following three lines link to jquery, bootstrap, and -->
<!-- my own Javascript files -->
<script src="https://code.jquery.com/w3/1.4.5/jquery.w3-1.4.5.min.js">
</script>
<script type="text/javascript" src="js/bootstrap.min.js"></script>
<script type="text/javascript" src="javascript/javascript.js"></script>
</head>
<!-- this is the start of the web site body -->
<!-- the 'class' attribute specifies the css that this body uses to -->
<!-- beautify itself -->
<!-- disregard the theme class, but make use of the color class -->
<!-- this is where you set your body background color, light grey, in this -->
<!-- case! -->
<!-- check out the list of pre-made colors at the bottom of this listing -->
<!-- in this body is where you also set your text size using w3-tiny -->
<!-- w3-small, w3-medium, w3-large, w3-xlarge, w3-xxlarge, -->
<!-- w3-xxxlarge, w3-jumbo -->
<!-- as you use W3Schools templates, you can put multiple css classes in an
element, i.e., <body>, <div>, <span>, <p>, <a>, <button>, <img>, etc. -->
<body class="w3-theme-l5 w3-light-grey">
<!-- some of the following codes were broken down into multiple lines -->
<!-- to fit the screen display -->
<!-- Navbar -->
<!-- this is the div that wraps around the navbar -->
<div class="w3-top">
<!-- in the navbar you can style the look-and-feel using css classes. -->
<!-- for example, you can make the navbar thicker or thiner by specifying -->
<!-- the class as w3-padding-tiny, w3-padding-small, -->
<!-- w3-padding-large, etc. -->
<!-- in the example site illustrated above I style the navbar as w3-blue! -->
<div class="w3-bar w3-theme-d2 w3-left-align w3-small w3-blue">
<a class="w3-bar-item w3-button w3-hide-medium w3-hide-large w3-right
w3-padding-small w3-hover-white w3-small w3-theme-d2"
href="javascript:void(0);" onclick="openNav()">
<i class="fa fa-bars"></i></a>
<!-- notice that the anchor tags contain "#" used in place ---->
<!-- of the actual url that you need to provide! ---->
<!-- the "#" is just a placeholder for the real url! ---->
<!-- so don't forget to replace "#" with the actual url! ---->
<!-- for example: "http://www.example.com/homefolder/myfile.php" ---->
<a href="#" class="w3-bar-item w3-button w3-padding-large w3-theme-d4">
<i class="fa fa-home w3-margin-right"></i>Logo</a>
<a href="#" class="w3-bar-item w3-button w3-hide-small w3-padding-large
w3-hover-white" title="News"><i class="fa fa-globe"></i></a>
<a href="#" class="w3-bar-item w3-button w3-hide-small w3-padding-large
w3-hover-white" title="Account Settings"><i class="fa fa-user"></i></a>
<a href="#" class="w3-bar-item w3-button w3-hide-small w3-padding-large
w3-hover-white" title="Messages"><i class="fa fa-envelope"></i>
<div class="w3-dropdown-hover w3-hide-small">
<button class="w3-button w3-padding-large" title="Notifications">
<i class="fa fa-bell"></i>
<span class="w3-badge w3-right w3-small w3-green">3</span>
</button>
<!-- here is again the use of "#" as a placeholder for the real url! ---->
<div class="w3-dropdown-content w3-card-4 w3-bar-block"
style="width:300px">
<a href="#" class="w3-bar-item w3-button">One new friend request</a>
<a href="#" class="w3-bar-item w3-button">John Doe posted on
your wall</a>
<a href="#" class="w3-bar-item w3-button">Jane likes your post</a>
</div>
</div>
<a href="#" class="w3-bar-item w3-button w3-hide-small w3-right
w3-padding-medium w3-hover-white" title="My Account">
<img src="./image/paul_tuon.jpg" class="w3-circle"
style="height:23px;width:23px" alt="Avatar"> </a>
</div>
</div> <!-- end div class="w3-top" -->
<!-- the following code block is the code that gets used instead of the -->
<!-- above navbar when a mobile device is used to load -->
<!-- this web site -->
<!-- Navbar on small screens -->
<!-- here is again the use of "#" as a placeholder for the real url! ---->
<div id="navDemo" class="w3-bar-block w3-theme-d2 w3-hide
w3-hide-large w3-hide-medium w3-large">
<a href="#" class="w3-bar-item w3-button w3-padding-large">Link 1</a>
<a href="#" class="w3-bar-item w3-button w3-padding-large">Link 2</a>
<a href="#" class="w3-bar-item w3-button w3-padding-large">Link 3</a>
<a href="#" class="w3-bar-item w3-button w3-padding-large">My Profile</a>
</div>
<!-- now the navbar code is done! -->
<!-- at this point there are 0 open <div> tag -->
<!-- Page Container -->
<!-- remember that there are typically four sections in a web site: -->
<!-- the head section, the navbar section, the main body content, -->
<!-- and the footer -->
<!-- so the following is the start of the main content of the web site, -->
<!-- and this section is the biggest section. -->
<!-- this main container has a maximum width of 1400 pixels -->
<!-- and spaces between the navbar and the start of the main -->
<!-- container or content is 80 pixels. -->
<!-- take a look at the gap in the web site above for a visual guide! -->
<!-- for a better practice is to use percentage as in 100% -->
<!-- of the screen width rather than specifying the exact width! -->
<!-- that way it works much better on different screen sizes! -->
<!-- pay special attention to one class: w3-container -->
<!-- 'container' is sort of a basket to hold something, in this case, -->
<!-- it holds a grid of column layout -->
<!-- in a later case, it holds a (small) profile container area! -->
<!-- as you can see, class w3-container can be used inside -->
<!-- another container area as well -->
<!-- in this case, this w3-container class acts as the main content -->
<!-- holder, holding everything in the body of the entire page! -->
<!-- remember that the whole website has four sections: navbar section, -->
<!-- head section, the main body section, and the footer section! -->
<!-- so this div has a w3-container class to hold the entire content -->
<!-- and this entire content is actually the 3-column layout grid! -->
<div class="w3-container w3-content" style="max-width:1400px; margin-top:80px">
<!-- The Grid -->
<!-- W3Schools provides grid system for us to use! -->
<!-- for a complete in depth tutorial see W3Schools on this topic! -->
<!-- pay special attention to a class called w3-row -->
<!-- so two classes that are central to W3Schools framework are -->
<!-- w3-container and w3-row -->
<!-- you'll make use of these two classes very often! -->
<!-- basically, the grid must be inside the container: w3-container! -->
<!-- and the container, w3-container, can contain rows of content! -->
<!-- this grid starts with a class w3-row -->
<!-- this is sort of the anchor div to hold the entire grid or one row! -->
<!-- class w3-row is a grid system. think of w3-row as a table row where -->
<!-- you can arrange grid data content in it. so if you have data content -->
<!-- that are normally arranged in rows in a table, you can use this -->
<!-- w3-row to hold those data content in table rows-like display! -->
<!-- however, in this website we have only one row of a table row! -->
<!-- if we have more data content that needs another table row, all we -->
<!-- have to do is create another div containing this w3-row class and -->
<!-- put it after the closing of this div shown below! -->
<!-- see the closing of this div later! -->
<!-- if you look at the website illustrated above, you'll see the -->
<!-- whole content body is inside a div that contains the class w3-row. -->
<!-- this is one row of content containing a three-column layout. -->
<!-- after the closing of this div w3-row, you can create more rows -->
<!-- of content by creating more divs that contain the class w3-row. -->
<!-- for each div that contains w3-row you can format your grid layout -->
<!-- any way you like, say, a four-column layout or whatever layout -->
<!-- configuration you desire! -->
<!-- here is the row! -->
<div class="w3-row">
<!-- here is inside the row! -->
<!-- now inside the anchor div or more specifically, -->
<!-- the w3-row (or grid) there are columns layout: a one-column -->
<!-- display, a two-column display, a three-column display, etc. -->
<!-- in this case, we have a three-column layout web site! -->
<!-- Left Column -->
<!-- this is the left column in the web site: see profile area column! -->
<!-- m3 is short for medium 3 out of 12 columns: 3-twelfth of the grid -->
<!-- W3Schools uses three sizes: small (s), medium (m), large (l) -->
<!-- so if you see s1 means a small scale grid with one-twelfth of -->
<!-- the grid. m7 is a medium scale layout with 7/12 of the total -->
<!-- grid layout. -->
<!-- likewise, an l2 (that is "L" and 2) means 1arge scale layout-->
<!-- with a two-twelfth of the total grid layout! -->
<!-- here, we have a medium scale with 3/12th of the total grid layout -->
<!-- as you can see, this left column has a class w3-container to hold -->
<!-- the entire left side area! -->
<!-- as stated above, class w3-container can be used inside this -->
<!-- container area as well! sort of containers within container! -->
<div class="w3-col m3 w3-container">
<!-- Profile -->
<!-- w3-card is a class to make the profile looks like a deck -->
<!-- of cards, w3-round will make the deck of cards rounded -->
<!-- edges on all 4 corners -->
<div class="w3-card w3-round w3-light-blue">
<!-- here is where class w3-container gets used to hold-->
<!-- a profile area -->
<div class="w3-container">
<h4 class="w3-center">My Profile</h4>
<p class="w3-center"><img src="./image/paul_tuon.jpg"
class="w3-circle" style="height:106px;width:106px"
alt="A Profile Picture"></p>
<hr>
<p><i class="fa fa-pencil fa-fw w3-margin-right
w3-text-theme"></i> Designer, UI</p>
<p><i class="fa fa-home fa-fw w3-margin-right
w3-text-theme"></i> Minneapolis, MN (US)</p>
<p><i class="fa fa-birthday-cake fa-fw w3-margin-right
w3-text-theme"></i> April 1, 2020</p>
</div>
</div>
<br>
<!-- Accordion -->
<!-- this block of code contains an accordion-like feature -->
<!-- when a user clicks on an item it slides down to reveal the content! -->
<!-- class w3-card is a css that made to look like a deck of cards -->
<div class="w3-card w3-round">
<div class="w3-pale-blue">
<!-- when a user clicks on "My Groups" it calls myFunction() -->
<!-- and it displays an accordion style revealing the content -->
<!-- you might want to experiment using other elements such -->
<!-- as div or span or other elements instead of button! -->
<button onclick="myFunction('Demo1')" class="w3-button
w3-block w3-theme-l1 w3-left-align">
<i class="fa fa-circle-onotch fa-fw w3-margin-right">
My Groups</i></button>
<!-- here is again w3-container gets used! -->
<!-- note that w3-hide hides the content inside the -->
<!-- div when the page is loaded! -->
<!-- it will only reveal the content when a user clicks -->
<!-- on "My Groups"! -->
<div id="Demo1" class="w3-hide w3-container">
<p>Some text..</p>
</div>
<!-- when a user clicks on "My Events" it calls myFunction() -->
<!-- and it displays an accordion style calendar of events -->
<!-- by sliding down to reveal the content -->
<!-- you might want to experiment using other elements such -->
<!-- as div or span or other elements instead of button! -->
<!-- right here where you might want to place a break: "<br>" -->
<!-- to make the gap between the two accordion item elements! -->
<!-- so instead of using "<br>" you might want to use -->
<!-- css styling to specify how much gap you want because -->
<!-- "<br>" might be bigger/smaller gap than you like! -->
<!-- so using css to style the gap is probably a good idea! -->
<button onclick="myFunction('Demo2')" class="w3-button w3-block
w3-theme-l1 w3-left-align"><i class="fa fa-calendar-check-0
fa-fw w3-margin-right"> My Events</i></button>
<!-- here is again w3-container gets used! -->
<!-- again w3-hide hides the content inside the -->
<!-- div when the page is loaded! -->
<!-- it will only reveal the content when a user clicks -->
<!-- on "My Events"! -->
<div id="Demo2" class="w3-hide w3-container">
<p>Some other text..</p>
</div>
<!-- likewise, when a user clicks on "My Photos" it calls -->
<!-- myFunction() and it displays an accordion style album -->
<!-- of photos by sliding down to reveal the photos in a -->
<!-- two-column layout -->
<!-- if you provide photos in the below container: a photo -->
<!-- album container, it will display them when a user -->
<!-- clicks on "My Photos" -->
<!-- you might want to experiment using other elements such -->
<!-- as div or span or other elements instead of button! -->
<!-- right here where you might want to place a break: "<br>" -->
<!-- to make the gap between the two accordion item elements! -->
<!-- so instead of using "<br>" you might want to use -->
<!-- css styling to specify how much gap you want because -->
<!-- "<br>" might be bigger/smaller gap than you like! -->
<!-- so using css to style the gap is probably a good idea! -->
<button onclick="myFunction('Demo3')" class="w3-button
w3-block w3-theme-l1 w3-left-align">
<i class="fa fa-user fa-fw w3-margin-right"> My Photos
</i></button>
<!-- class w3-container is used to hold the photos album layout -->
<!-- w3-hide is a class to hide the element: diplay: none -->
<!-- as you can see, when the web site is loaded, "Demo3" is -->
<!-- not shown! -->
<!-- it will only be shown when a user clicks on -->
<!-- "My Photos" button! -->
<div id="Demo3" class="w3-hide w3-container">
<div class="w3-row-padding">
<br>
<!-- the following is where you put your photo album! -->
<!-- class w3-half is a grid layout as a two-column -->
<!-- layout relative to the class w3-container used -->
<!-- in the album layout so the photos are arranged -->
<!-- side by side as a two-column layout -->
<div class="w3-half">
<img src="./image/paul_tuon.jpg" style="width: 100%"
class="w3-margin-bottom">
</div>
<div class="w3-half">
<img src="./image/graduation.jpg" style="width: 100%"
class="w3-margin-bottom">
</div>
<!-- this is another two-column grid stacking below above -->
<div class="w3-half">
<img src="./image/paul_tuon.jpg" style="width: 100%"
class="w3-margin-bottom">
</div>
<div class="w3-half">
<img src="./image/graduation.jpg" style="width: 100%"
class="w3-margin-bottom">
</div>
<!-- this is another two-column grid stacking below above -->
<div class="w3-half">
<img src="image/example5.jpg" style="width: 100%"
class="w3-margin-bottom">
</div>
<div class="w3-half">
<img src="image/graduation.jpg" style="width: 100%"
class="w3-margin-bottom">
</div>
</div> <!-- end div class="w3-row-padding" -->
</div> <!-- end div id="Demo3" -->
</div> <!-- end div class="w3-white" -->
</div> <!-- end div class="w3-card w3-round" -->
<!-- this is the end of an accordion-like feature! -->
<!-- at this point there are still 3 open div -->
<!-- Interest: the miscellaneous content of interest! -->
<!-- w3-hide-small is to not display the content when mobile -->
<!-- device is used to load the web site! so "Interests" content -->
<!-- won't be loaded if mobile device is being used to load -->
<!-- this web site -->
<div class="w3-card w3-round w3-teal w3-hide-small">
<div class="w3-container">
<p>Interests</p>
<p>
<span class="w3-tag w3-small w3-theme-d5">News</span>
<span class="w3-tag w3-small w3-theme-d4">W3Schools</span>
<span class="w3-tag w3-small w3-theme-d3">Labels</span>
<span class="w3-tag w3-small w3-theme-d2">Games</span>
<span class="w3-tag w3-small w3-theme-d1">Friends</span>
<span class="w3-tag w3-small w3-theme">Games</span>
<span class="w3-tag w3-small w3-theme-l1">Friends</span>
<span class="w3-tag w3-small w3-theme-l2">Food</span>
<span class="w3-tag w3-small w3-theme-l3">Design</span>
<span class="w3-tag w3-small w3-theme-l4">Art</span>
<span class="w3-tag w3-small w3-theme-l5">Photos</span>
</p>
</div>
</div>
The following block of code contained in the original template
<!-- Alert box -->
<!-- when a user clicks on this div area an alert box pops up -->
<!--
<div class="w3-container w3-display-container w3-round w3-theme-14
w3-border w3-theme-border w3-margin-bottom w3-hide-small w3-red">
<span onclick="this.parentElement.style.display='none'"
class="w3-button w3-theme-13 w3-display-topright">
<i class="fa fa-remove"></i>
</span>
<p><strong>Hey,</strong></p>
<p>People are looking at your profile. Find out who!</p>
</div>
-->
</div> <!-- end left column -->
<!-- at this point there are still 2 open <div> tags -->
<!-- start middle column -->
<!-- this is the start of the middle column. -->
<!-- size m7 means 7/12 of the grid -->
<!-- as you can figure it out: there are 12 columns in the entire grid -->
<!-- if the left side column is m3, meaning 3/12 of the grid, -->
<!-- and middle column is 7/12 of the grid, -->
<!-- the right column has to be 2/12 of the grid! -->
<div class="w3-col m7">
<!-- right here where I add some new content to the middle column -->
<!-- I add a scrolling message board to make it more flashy. for example: -->
<div class="w3-row-padding">
<!-- notice that you need to use the entire length of the grid: m12 -->
<!-- meaning the entire middle column -->
<div class="w3-col m12">
<div class="w3-card-2 w3-round w3-white">
<div class="w3-container w3-padding">
<marquee bgcolor=white width="100%" height="50">
<font size="5" color="#FF66FF">
Welcome to the 21st century and beyond where digital mobile rules!</font>
<font size="5" color="#1883FF">More content to scroll!</font>
</marquee>
</div>
</div>
</div>
</div>
<div class="w3-row-padding">
<div class="w3-col m12">
<div class="w3-card w3-round w3-white">
<div class="w3-container w3-padding">
<h6 class="w3-opacity">Social Media Template</h6>
<p contenteditable="true" class="w3-border
w3-padding">Status: Feeling blue!</p>
<button type="button" class="w3-button w3-theme">
<i class="fa fa-pencil"></i> Post
</button>
</div>
</div>
</div>
</div>
<div class="w3-container w3-card w3-round w3-blue w3-margin">
<img src="./image/paul_tuon.jpg" alt="Avatar" class="w3-left
w3-circle w3-margin-right" style="width:60px">
<span class="w3-right w3-opacity">1 min</span>
<h4>John Doe</h4>
<hr class="w3-clear">
<p>This is just an ordinary content! You can put whatever
content you want!</p>
<div class="w3-row-padding" style="margin:0 -16px">
<!--
<div class="w3-half">
<img src="./image/graduation.jpg" alt="just a picturer"
style="width: 100%" class="w3-margin-bottom">
</div>
<div class="w3-half">
<img src="./image/paul_tuon.jpg" alt="another picture"
style="width: 100%" class="w3-margin-bottom">
</div>
-->
</div>
<button type="button" class="w3-button w3-theme-d1 w3-margin-bottom">
<i class="fa fa-thumbs-up"></i> Like</button>
<button type="button" class="w3-button w3-theme-d2 w3-margin-bottom">
<i class="fa fa-comment"></i> Comment</button>
</div>
<div class="w3-container w3-card w3-round w3-khaki w3-margin"><br>
<!--
<img src="./image/graduation.jpg" alt="Avatar" class="w3-left
w3-circle w3-margin-right" style="width:60px">
-->
<span class="w3-right w3-opacity">16 min</span>
<h4>Jane Doe</h4>
<hr class="w3-clear">
<p>Lorem ipsum dolor. Lorem ipsum dolor. Lorem ipsum dolor.
Lorem ipsum dolor. Lorem ipsum dolor.</p>
<button type="button" class="w3-button w3-theme-d1 w3-margin-bottom">
<i class="fa fa-thumbs-up"></i> Like</button>
<button type="button" class="w3-button w3-theme-d2 w3-margin-bottom">
<i class="fa fa-comment"></i> Comment</button>
</div>
The following block of code contained in the original template
<!--
<div class="w3-container w3-card w3-round w3-lime w3-margin"><br>
<img src="./image/paul_tuon.jpg" alt="Avatar" class="w3-left
w3-circle w3-margin-right" style="width:60px">
<span class="w3-right w3-opacity">30 min</span>
<h4>Angie Jane
<hr class="w3-clear">
<img src="./image/gradution.jpg" class="w3-margin-bottom"
style="width:100%">
<p>Lorem ipsum dolor. Lorem ipsum dolor. Lorem ipsum dolor.
Lorem ipsum dolor. Lorem ipsum dolor.</p>
<button type="button" class="w3-button w3-theme-d1 w3-margin-bottom">
<i class="fa fa-thumbs-up"></i> Like</button>
<button type="button" class="w3-button w3-theme-d2 w3-margin-bottom">
<i class="fa fa-comment"></i> Comment</button>
</div>
-->
<!-- on the left side column there is an accordion slide down/up -->
<!-- feature which contains three sections: My Groups, My Events, -->
<!-- My Photos! you can use that code example to place your -->
<!-- accordion feature anywhere on the website! -->
<!-- let's put that same accordion feature in the middle column at -->
<!-- the very bottom just before the start of the footer! -->
<!-- just remember that each accordion item must contains -->
<!-- a unique id, e.g., group, event, photo! -->
<!-- start accordion style feature! -->
<!-- Accordion -->
<div class="mobile-card mobile-round">
<div class="mobile-pale-blue">
<!-- when a user clicks on "My Groups" it will call -->
<!-- myFunction() and it displays an accordion -->
<!-- style revealing the content -->
<!-- you might want to experiment using other elements such -->
<!-- as div or span or other elements instead of button! -->
<button onclick="myFunction('group')"
class="mobile-button mobile-block mobile-theme-l1
mobile-left-align">
<i class="fa fa-circle-onotch fa-fw
mobile-margin-right"> My Groups</i>
</button>
<div id="group" class="mobile-hide mobile-container">
<p>Some text..</p>
</div>
<!-- when a user clicks on "My Events" it will call -->
<!-- myFunction() and it displays an accordion -->
<!-- style calendar of events by sliding down to -->
<!-- reveal the content! -->
<!-- you might want to experiment using other elements such -->
<!-- as div or span or other elements instead of button! -->
<button onclick="accordion('event')"
class="mobile-button mobile-block mobile-theme-l1
mobile-left-align">
<i class="fa fa-calendar-check-0 fa-fw
mobile-margin-right"> My Events</i>
</button>
<div id="event" class="mobile-hide mobile-container">
<p>Some other text..</p>
<div>
<!-- likewise, when a user clicks on "My Photos" it calls -->
<!-- myFunction() and it displays an accordion style -->
<!-- album of photos by sliding down to reveal the photos -->
<!-- in a two-column layout -->
<!-- if you provide photos in the below container: a photo -->
<!-- album container! it will display them when a user -->
<!-- clicks on "My Photos" -->
<!-- the below layout is a two-column layout displaying -->
<!-- two photos side by side! -->
<!-- in this example, there are six photos displaying -->
<!-- in pairs to make it three rows! -->
<!-- you might want to experiment using other elements such -->
<!-- as div or span or other elements instead of button! -->
<span class="hljs-string"><button onclick="accordion('photo')"
class="mobile-button mobile-block mobile-theme-l1
mobile-left-align"><i class="fa fa-user
fa-fw mobile-margin-right"> My Photos</i>
</button>
<div id="photo" class="mobile-hide mobile-container">
<div class="mobile-row-padding">
<br>
<div class="mobile-half">
<img src="./image/paul_tuon.jpg" style="width: 100%"
class="mobile-margin-bottom">
</div>
<div class="mobile-half">
<img src="./image/paul_tuon_graduation.jpg"
style="width: 100%" class="mobile-margin-bottom">
</div>
<div class="mobile-half">
<img src="./image/paul_tuon.jpg"
style="width: 100%" class="mobile-margin-bottom">
</div>
<div class="mobile-half">
<img src="./image/paul_tuon_graduation.jpg"
style="width: 100%" class="mobile-margin-bottom">
</div>
<div class="mobile-half">
<img src="image/paul_tuon.jpg"
style="width: 100%" class="mobile-margin-bottom">
</div>
<div class="mobile-half">
<img src="image/paul_tuon_graduation.jpg"
style="width: 100%" class="mobile-margin-bottom">
</div>
</div> <!-- end div class="mobile-row-padding" -->
</div> <!-- end div id="photo" -->
</div> <!-- end div class="mobile-pale-blue" -->
</div> <!-- end div class="mobile-card mobile-round" -->
<!-- end accordion style feature! -->
</div> <!-- end middle column -->
<!-- start right column -->
<!-- here it is: right column is 2/12 of the grid -->
<div class="w3-col m2">
<div class="w3-card w3-round w3-aqua w3-center">
<div class="w3-container">
<p>Upcoming Events:</p>
<img src="./image/image_105.jpg" class="w3-margin-bottom"
style="width:100%">
<p><strong>Holiday</strong></p>
<p>Friday 15:00</p>
<p><button type="button" class="w3-button w3-theme-14
w3-block">Info</button></p>
</div>
</div>
<div class="w3-card w3-round w3-pink w3-center">
<iv class="w3-container">
<p>Friend Request</p>
<!--
<img src="./image/graduation.jpg" class="w3-margin-bottom"
style="width:50%">
-->
<span>Jane Doe</span>
<div class="w3-row w3-opacity">
<div class="w3-half">
<button type="button" class="w3-button w3-block-14
w3-green w3-section" title="Accept">
<i class="fa fa-check"></i></button>
</div>
<div class="w3-half">
<button type="button" class="w3-button w3-block-14
w3-red w3-section" title="Decline">
<i class="fa fa-remove"></i></button>
</div>
</div>
</div>
</div>
<br>
<div class="w3-card w3-round w3-purple w3-padding w3-center">
<p>ADS</p>
</div>
<br>
</div> <!-- end right column -->
<!-- here is the closing div for class w3-row! -->
</div> <!-- end grid containing class w3-row -->
<!-- right here, if you have more table rows-like data content, -->
<!-- you can add another div containing a class w3-row -->
<!-- after all the data content for this particular row has been -->
<!-- included, you can close out this div containing class w3-row -->
<!-- you can keep repeating this pattern over and over as you -->
<!-- need to make your website looks like table rows-like content! -->
<!-- the rows have to be inside the closing of the div that -->
<!-- contains w3-container! -->
<!-- here is the closing div that contains class w3-container! -->
</div> <!-- end page container -->
<!-- at this point all open div tags have been closed -->
<!-- so the grid system is very simple. -->
<!-- it only contains two classes: w3-container and w3-row -->
<!-- that's all! -->
<!-- anything inside the grid are just ordinary html elements: -->
<!-- div, p, span, etc. -->
<!-- as you can see from the above grid, -->
<!-- it contains only one w3-container and one w3-row -->
<!-- that's all! -->
<!-- here is the last section of the website: footer -->
<!-- start footer -->
<footer class="w3-container w3-theme-d3 w3-padding-16">
<div>Follow us on social medias: Facebook, Twitter, Instagram!</div>
<div class="w3-right">Contact: john@doe.com</div>
</footer>
<script>
// Accordion
function myFunction(id)
{
var x = document.getElementById(id);
if (x.className.indexOf("w3-show") == -1)
{
x.className += " w3-show";
x.previousElementSibling.className += " w3-theme-d1";
}
else
{
x.className = x.className.replace("w3-show", "");
x.previousElementSibling.className =
x.previousElementSibling.className.replace(" w3-theme-d1", "");
}
}
// used to toggle on smaller screen when clicking on the menu button
function openNav()
{
var x = document.getElementById("navDemo");
if (x.className.indexOf("w3-show") == -1)
{
x.className += " w3-show";
}
else
{
x.className = x.className.replace(" w3-show", "");
}
}
</script>
</body>
</html>
/* Here is the listing of colors. see css file for more definitions */
/* Colors */
.w3-amber, .w3-hover-amber:hover{color:#000!important;
background-color:#ffc107!important}
.w3-aqua,.w3-hover-aqua:hover{color:#000!important;
background-color:#00ffff!important}
.w3-blue,.w3-hover-blue:hover{color:#fff!important;
background-color:#2196F3!important}
.w3-light-blue,.w3-hover-light-blue:hover{color:#000!important;
background-color:#87CEEB!important}
.w3-brown,.w3-hover-brown:hover{color:#fff!important;
background-color:#795548!important}
.w3-cyan,.w3-hover-cyan:hover{color:#000!important;
background-color:#00bcd4!important}
.w3-blue-grey,.w3-hover-blue-grey:hover,.w3-blue-gray,
.w3-hover-blue-gray:hover{color:#fff!important;
background-color:#607d8b!important}
.w3-green,.w3-hover-green:hover{color:#fff!important;
background-color:#4CAF50!important}
.w3-light-green,.w3-hover-light-green:hover{color:#000!important;
background-color:#8bc34a!important}
.w3-indigo,.w3-hover-indigo:hover{color:#fff!important;
background-color:#3f51b5!important}
.w3-khaki,.w3-hover-khaki:hover{color:#000!important;
background-color:#f0e68c!important}
.w3-lime,.w3-hover-lime:hover{color:#000!important;
background-color:#cddc39!important}
.w3-orange,.w3-hover-orange:hover{color:#000!important;
background-color:#ff9800!important}
.w3-deep-orange,.w3-hover-deep-orange:hover{color:#fff!important;
background-color:#ff5722!important}
.w3-pink,.w3-hover-pink:hover{color:#fff!important;
background-color:#e91e63!important}
.w3-purple,.w3-hover-purple:hover{color:#fff!important;
background-color:#9c27b0!important}
.w3-deep-purple,.w3-hover-deep-purple:hover{color:#fff!important;
background-color:#673ab7!important}
.w3-red,.w3-hover-red:hover{color:#fff!important;
background-color:#f44336!important}
.w3-sand,.w3-hover-sand:hover{color:#000!important;
background-color:#fdf5e6!important}
.w3-teal,.w3-hover-teal:hover{color:#fff!important;
background-color:#009688!important}
.w3-yellow,.w3-hover-yellow:hover{color:#000!important;
background-color:#ffeb3b!important}
.w3-white,.w3-hover-white:hover{color:#000!important;
background-color:#fff!important}
.w3-black,.w3-hover-black:hover{color:#fff!important;
background-color:#000!important}
.w3-grey,.w3-hover-grey:hover,.w3-gray,
.w3-hover-gray:hover{color:#000!important;
background-color:#9e9e9e!important}
.w3-light-grey,.w3-hover-light-grey:hover,.w3-light-gray,
.w3-hover-light-gray:hover{color:#000!important;
background-color:#f1f1f1!important}
.w3-dark-grey,.w3-hover-dark-grey:hover,.w3-dark-gray,
.w3-hover-dark-gray:hover{color:#fff!important;
background-color:#616161!important}
.w3-pale-red,.w3-hover-pale-red:hover{color:#000!important;
background-color:#ffdddd!important}
.w3-pale-green,.w3-hover-pale-green:hover{color:#000!important;
background-color:#ddffdd!important}
.w3-pale-yellow,.w3-hover-pale-yellow:hover{color:#000!important;
background-color:#ffffcc!important}
.w3-pale-blue,.w3-hover-pale-blue:hover{color:#000!important;
background-color:#ddffff!important}
.w3-text-amber,.w3-hover-text-amber:hover{color:#ffc107!important}
.w3-text-aqua,.w3-hover-text-aqua:hover{color:#00ffff!important}
.w3-text-blue,.w3-hover-text-blue:hover{color:#2196F3!important}
.w3-text-light-blue,.w3-hover-text-light-blue:hover{color:#87CEEB!important}
.w3-text-brown,.w3-hover-text-brown:hover{color:#795548!important}
.w3-text-cyan,.w3-hover-text-cyan:hover{color:#00bcd4!important}
.w3-text-blue-grey,.w3-hover-text-blue-grey:hover,.w3-text-blue-gray,
.w3-hover-text-blue-gray:hover{color:#607d8b!important}
.w3-text-green,.w3-hover-text-green:hover{color:#4CAF50!important}
.w3-text-light-green,.w3-hover-text-light-green:hover{color:#8bc34a!important}
.w3-text-indigo,.w3-hover-text-indigo:hover{color:#3f51b5!important}
.w3-text-khaki,.w3-hover-text-khaki:hover{color:#b4aa50!important}
.w3-text-lime,.w3-hover-text-lime:hover{color:#cddc39!important}
.w3-text-orange,.w3-hover-text-orange:hover{color:#ff9800!important}
.w3-text-deep-orange,.w3-hover-text-deep-orange:hover{color:#ff5722!important}
.w3-text-pink,.w3-hover-text-pink:hover{color:#e91e63!important}
.w3-text-purple,.w3-hover-text-purple:hover{color:#9c27b0!important}
.w3-text-deep-purple,.w3-hover-text-deep-purple:hover{color:#673ab7!important}
.w3-text-red,.w3-hover-text-red:hover{color:#f44336!important}
.w3-text-sand,.w3-hover-text-sand:hover{color:#fdf5e6!important}
.w3-text-teal,.w3-hover-text-teal:hover{color:#009688!important}
.w3-text-yellow,.w3-hover-text-yellow:hover{color:#d2be0e!important}
.w3-text-white,.w3-hover-text-white:hover{color:#fff!important}
.w3-text-black,.w3-hover-text-black:hover{color:#000!important}
.w3-text-grey,.w3-hover-text-grey:hover,.w3-text-gray,
.w3-hover-text-gray:hover{color:#757575!important}
.w3-text-light-grey,.w3-hover-text-light-grey:hover,
.w3-text-light-gray,.w3-hover-text-light-gray:hover{color:#f1f1f1!important}
.w3-text-dark-grey,.w3-hover-text-dark-grey:hover,
.w3-text-dark-gray,.w3-hover-text-dark-gray:hover{color:#3a3a3a!important}
/* can you make sense of the above color definitions? */
/* let's take the last color definition above: the last line! */
.w3-text-dark-gray,.w3-hover-text-dark-gray:hover{color:#3a3a3a!important}
/* format it like this for a better visualization: */
.w3-text-dark-gray,
.w3-hover-text-dark-gray:hover
{
color:#3a3a3a!important
}
/* there are two classes: one is w3-text-dard-gray and the other */
/* is w3-hover-text-dark-gray which is attached to a hover mouse event. */
/* both of these two classes are assigned a color of a dark-gray */
/* which is #3a3a3a */
/* disregard the word "!important" for now. you can learn more in */
/* the css tutorial provided by W3Schools */
/* if you decide to add your own css definition, just add them to */
/* the bottom of the w3.css file. */
/* for example, if you find that the pre-made colors provided by */
/* W3Schools are not enough to your liking, you can add more color */
/* definitions to w3.css file like this: */
.w3-slate-gray
{
/** don't forget to put "!important" as well! **/
color:#ebe2e1!important
}
/* you can add other definitions to w3.css file as well because */
/* w3.css is only a css file framework that contains the universal */
/* commonly used definitions. */
/* so you most certainly need to add your own css defitions to */
/* the w3.css file */
/* A SECRET TO MEMORIZING CSS ATTRIBUTES or PROPERTIES */
/* one of the most confusing things in CSS is memorizing */
/* attributes/properties */
/* what if you have an attribute that says: */
/* padding: 10px 5px 20px 10px */
/* what does that mean? */
/* it means the padding property has four values:
top padding is 10px
right padding is 5px
bottom padding is 20px
left padding is 10px
*/
/* so how do you remember them? */
/* by brute force? */
/* that's what most people do: remembering it by brute force! */
/* but there is an easier way to remembering them and here's how: */
/* first, think of all HTML elements as a box. well, to be honest */
/* all HTML elements (div, p, span, a, button, i, etc) are boxes! */
/* and boxes have four sides and four corners! */
/* when you style an HTML element using padding you actually are */
/* styling the four sides and four corners! */
/* if you follow the definition above it says padding 10px 5px 20px 10px */
/* it basically tells you to follow the box sitting stationary upright */
/* think of it as an ordinary box that is square sitting stationary upright */
/* an ordinary square box has four sides and four corners */
/* starting from the top of the box, which is 10px in height, and */
/* then follow the box around, which is to the right side of the box! */
/* in the right side of the box is where you find a 5px wide space gap! */
/* now you're done with the top and the right side of the box, so you continue */
/* on around the box, which is to the bottom of the box containing 20px in */
/* height! */
/* do you see what's happening? */
/* you basically follow the box around until you end up at the same place that */
/* you started, which is at the top of the box sitting stationary upright */
/* remember that a box has four sides and four corners! */
/* so you need to follow the box around the four corners! */
/* now you're at the bottom of the box and you continue to follow */
/* the box around, which is to the left side of the box containing */
/* a 10px wide gap! */
/* There you have it! */
/* A secret to memorizing the CSS attributes! */
/* what if you have something like the following illustrations? */
/* the same thing: follow the box! well, sort of! but you get the idea!
if the padding property has three values:
padding: 25px 50px 75px;
top padding is 25px
right and left paddings are 50px
bottom padding is 75px
above, start at the top of the box and move to the right side of the box!
now since right and left are together, it is a common value for both!
from there, you continue on around the box until all four sides are met!
if the padding property has two values:
padding: 25px 50px;
top and bottom paddings are 25px
right and left paddings are 50px
this is where the rule is broken and makes an exception, but still not
too far from the rule!
top and bottom go together and right and left also go together!
as you can see, you follow the same box rule logic!
if the padding property has one value:
padding: 25px;
all four paddings are 25px
this one is not obvious to the human eyes but the browsers style it
using the box rule by first styling the top and then the right and
then the bottom and finally the left side of the box!
*/
/* YOUR OWN CSS DEFINITIONS */
/* most likely you will need to create your own CSS definitions */
/* to fullfil your needs! */
/* when you create your own definitions make sure that you use your */
/* own prefix and not the 'w3' prefix so that to avoid conflict! */
/* the color, padding, margin size, and text size are probably the */
/* most definitions you might need to create to fullfil your needs! */
/* for example, in most cases, you might need to style the left side */
/* margin only by using a 'my-padding-left-10 or my-margin-left-20 or
whatever margin or padding size you need!
.my-padding-left-10
{
/* here is where you specify the size */
padding-left:10px!important;
}
.my-margin-left-20
{
/* here is where you specify the size */
margin-left:20px!important;
}
*/
/* there you have it! */
/* please check out tutorials at the W3Schools.com for more */
/* on this topic! */
For more about colors, please see my tutorial called an introduction to colors!
To get your own color check this out: color picker!
As mentioned earlier, the best place to advance your programming skills is the W3Schools. One particular topic that you might want to spend some time on learning is the image tutorial. You can learn how to place background images on your website as well as learning how to make your images work on mobile devices. So there are lots of topics available for you to improve your programming skills.
While you're at it learning about images, you might want to spend some time learning this important CSS class that makes displaying images awesome. The CSS class is called "clearfix" and can be found here: https://www.w3schools.com/howto/howto_css_clearfix.asp
Also, while you're at it learning about CSS, you might find these topics interesting and useful as well. Check the following topics out:
Best Free JavaScript & CSS/CSS3 Libraries For Modern Web Design
For more good stuffs, particularly photo galleries, sliders and plugins, please check out this site called https://www.jqueryscript.net/
There you have it! So go at it!!!
First, you need to visit the jqueryscript.net mentioned above and browse through their sliders. Once you've decided which one you want, go ahead and download their plugin and go from there. Each plugin has a demo for you to see a preview of what it should look like. It also has a tutorial to help you incorporate it in your website.
For this tutorial, I chose one of the jquery slider plugin that I found on the Internet and it is called CarouFredSel. Here is the link to that plugin: https://github.com/DivaVocals/carouFredSel
If you want to use this plugin, you need to download the plugin from the link mentioned above and extract it. The plugin as usual comes in a zip package, so you definitely need a zip software installed on your computer to extract it. See instruction on zip application earlier at the beginning of this tutorial.
Once you'd downloaded and extracted it, you can view the demo contains in file index.html inside the main folder called 'carouFredSel-master'. Just double-click on the file index.html and it will activate a demo screen showing the various styles of the slider that you can use to incorporate in your own website.
Let's incorporate that plugin in the example website shown above.
File: index.php
<!DOCTYPE html>
<html>
<head>
<title>Template</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- include jQuery + carouFredSel plugin -->
<!-- right here where you link to a jquery library that -->
<!-- is hosted in a Content Delivery Network or CDN -->
<!-- a CDN is just a central data network that mainly delivering -->
<!-- data content to users via a link! -->
<script type="text/javascript" language="javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<!-- this CDN is owned by Google! -->
<!-- so Google is hosting the jquery library for everyone to link to -->
<!-- and use it instead of embedding that jquery library in their own script! -->
<!-- personally, I recommend that you embedd jquery library in your own -->
<!-- script instead of linking to a CDN! -->
<!-- to embedd a jquery library in your own script, do like the following -->
<!-- assuming you'd downloaded the jquery and place that library in a folder -->
<!-- called js/jquery -->
<script type="text/javascript" language="javascript"
src="js/jquery/jquery.min.js"></script>
<!-- to download the jquery library you -->
<!-- need to go to the jquery website: -->
<!-- https://jquery.com/download/ -->
<!-- click on the "Download the compressed, production" -->
<!-- and just hilight the whole file content and -->
<!-- copy and paste it in a blank file and name it accordingly! -->
<!-- in my case above, I named the jquery library file name to -->
<!-- 'jquery.min.js' -->
<!-- do not include both the CDN and the embedded library at the -->
<!-- same time because it might cause problems! -->
<!-- so use one or the other and not both of them at the same time! -->
<!-- next is the link to the carouFredSel library stored in the -->
<!-- plugin folder called carouFredSel-master -->
<script type="text/javascript" language="javascript"
src="jquery.carouFredSel-6.2.1-packed.js"></script>
<!-- optionally include helper plugins -->
<script type="text/javascript" language="javascript"
src="helper-plugins/jquery.mousewheel.min.js"></script>
<script type="text/javascript" language="javascript"
src="helper-plugins/jquery.touchSwipe.min.js"></script>
<script type="text/javascript" language="javascript"
src="helper-plugins/jquery.transit.min.js"></script>
<script type="text/javascript" language="javascript"
src="helper-plugins/jquery.ba-throttle-debounce.min.js"></script>
<link rel="stylesheet" href="./css/mobile.css">
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/
css/font-awesome.min.css">
<link rel="stylesheet"
href="http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/
3.2.0/css/bootstrap.min.css">
<script src="https://code.jquery.com/w3/1.4.5/jquery.w3-1.4.5.min.js">
</script>
<script type="text/javascript" src="js/bootstrap.min.js"></script>
<script type="text/javascript" src="javascript/javascript.js">
</script>
<!-- start plugin onDocumentReady -->
<script type="text/javascript" language="javascript">
$(function()
{
// Responsive layout, resizing the items
$('#foo4').carouFredSel(
{
responsive: true,
width: '100%',
scroll: 2,
items:
{
// the sliding content's width
// if you set it to half the
// screen size it will show two
// images at a time.
// if you set it to full screen
// (1000 pixels) it will show one
// image at a time.
width: 400,
// commenting out the optionally
// resize item-height option
// height: '30%',
visible:
{
min: 2,
max: 6
}
}
}
);
}
</script>
<style type="text/css" media="all">
.list_carousel
{
background-color: #ccc;
margin: 0 0 30px 60px;
width: 360px;
}
.list_carousel ul
{
margin: 0;
padding: 0;
list-style: none;
display: block;
}
.list_carousel li
{
font-size: 40px;
color: #999;
text-align: center;
background-color: #eee;
border: 5px solid #999;
width: 50px;
height: 50px;
padding: 0;
margin: 6px;
display: block;
float: left;
}
.list_carousel.responsive
{
width: auto;
margin-left: 0;
}
.clearfix
{
float: none;
clear: both;
}
.prev
{
float: left;
margin-left: 10px;
}
.next
{
float: right;
margin-right: 10px;
}
</style>
</head>
<body class="w3-theme-l5 w3-light-grey">
<!-- some of the following codes were broken down into multiple lines -->
<!-- to fit the screen display -->
<!-- Navbar -->
<!-- this is the div that wraps around the navbar -->
<div class="w3-top">
<div class="w3-bar w3-theme-d2 w3-left-align w3-small w3-blue">
<a class="w3-bar-item w3-button w3-hide-medium w3-hide-large w3-right
w3-padding-small w3-hover-white w3-small w3-theme-d2"
href="javascript:void(0);" onclick="openNav()">
<i class="fa fa-bars"></i></a>
<a href="#" class="w3-bar-item w3-button w3-padding-large w3-theme-d4">
<i class="fa fa-home w3-margin-right"></i>Logo</a>
<a href="#" class="w3-bar-item w3-button w3-hide-small w3-padding-large
w3-hover-white" title="News"><i class="fa fa-globe"></i></a>
<a href="#" class="w3-bar-item w3-button w3-hide-small w3-padding-large
w3-hover-white" title="Account Settings"><i class="fa fa-user"></i></a>
<a href="#" class="w3-bar-item w3-button w3-hide-small w3-padding-large
w3-hover-white" title="Messages"><i class="fa fa-envelope"></i>
<div class="w3-dropdown-hover w3-hide-small">
<button class="w3-button w3-padding-large" title="Notifications">
<i class="fa fa-bell"></i>
<span class="w3-badge w3-right w3-small w3-green">3</span>
</button>
<div class="w3-dropdown-content w3-card-4 w3-bar-block"
style="width:300px">
<a href="#" class="w3-bar-item w3-button">One new friend request</a>
<a href="#" class="w3-bar-item w3-button">John Doe posted on
your wall</a>
<a href="#" class="w3-bar-item w3-button">Jane likes your post</a>
</div>
</div>
<a href="#" class="w3-bar-item w3-button w3-hide-small w3-right
w3-padding-medium w3-hover-white" title="My Account">
<img src="./image/paul_tuon.jpg" class="w3-circle"
style="height:23px;width:23px" alt="Avatar"> </a>
</div>
</div> <!-- end div class="w3-top" -->
<!-- Navbar on small screens -->
<div id="navDemo" class="w3-bar-block w3-theme-d2 w3-hide
w3-hide-large w3-hide-medium w3-large">
<a href="#" class="w3-bar-item w3-button w3-padding-large">Link 1</a>
<a href="#" class="w3-bar-item w3-button w3-padding-large">Link 2</a>
<a href="#" class="w3-bar-item w3-button w3-padding-large">Link 3</a>
<a href="#" class="w3-bar-item w3-button w3-padding-large">My Profile</a>
</div>
<!-- now the navbar code is done! -->
<!-- at this point there are 0 open <div> tag -->
<!-- Slider Container -->
<div class="w3-container w3-content" style="max-width:1400px; margin-top:40px">
<div class="list_carousel responsive">
<!-- right here where the content of the slider is placed -->
<!-- notice that you can put any kind of content such as -->
<!-- text, images, etc., and as many content as you wish! -->
<!-- the slider will circle through the content until the end and loops -->
<!-- back to the beginning of the list! -->
<!-- the display of the images is dependenced on the size of the window -->
<!-- you set in the options of the function carouFredSel() above! -->
<!-- in the example above it was set to width: 400! -->
<ul id="foo4">
<li><img src="image/picture1.jpg"></li>
<li><img src="image/picture2.jpg"></li>
<li><img src="image/picture3.jpg"></li>
<li><img src="image/picture4.jpg"></li>
<li><img src="image/picture5.jpg"></li>
<li><img src="image/picture6.jpg"></li>
<li><img src="image/picture7.jpg"></li>
<li><img src="image/picture8.jpg"></li>
<li><img src="image/picture9.jpg"></li>
<li><img src="image/picture10.jpg"></li>
<li><img src="image/picture11.jpg"></li>
<li><img src="image/picture12.jpg"></li>
<li><img src="image/picture13.jpg"></li>
<li><img src="image/picture14.jpg"></li>
<li><img src="image/picture15.jpg"></li>
<li><img src="image/picture16.jpg"></li>
</ul>
<!-- for more tutorial on class "clearfix" please visit -->
<!-- https://www.w3schools.com/howto/howto_css_clearfix.asp -->
<div class="clearfix"></div>
</div>
</div>
<!-- Page Container -->
<div class="w3-container w3-content" style="max-width:1400px; margin-top:80px">
<!-- The Grid -->
<!-- here is the row! -->
<div class="w3-row">
<!-- Left Column -->
<div class="w3-col m3 w3-container">
<!-- Profile -->
<div class="w3-card w3-round w3-light-blue">
<div class="w3-container">
<h4 class="w3-center">My Profile</h4>
<p class="w3-center"><img src="./image/paul_tuon.jpg"
class="w3-circle" style="height:106px;width:106px"
alt="A Profile Picture"></p>
<hr>
<p><i class="fa fa-pencil fa-fw w3-margin-right
w3-text-theme"></i> Designer, UI</p>
<p><i class="fa fa-home fa-fw w3-margin-right
w3-text-theme"></i> Minneapolis, MN (US)</p>
<p><i class="fa fa-birthday-cake fa-fw w3-margin-right
w3-text-theme"></i> April 1, 2020</p>
</div>
</div>
<br>
<!-- Accordion -->
<div class="w3-card w3-round">
<div class="w3-pale-blue">
<button onclick="myFunction('Demo1')" class="w3-button
w3-block w3-theme-l1 w3-left-align">
<i class="fa fa-circle-onotch fa-fw w3-margin-right">
My Groups</i></button>
<div id="Demo1" class="w3-hide w3-container">
<p>Some text..</p>
</div>
<button onclick="myFunction('Demo2')" class="w3-button w3-block
w3-theme-l1 w3-left-align"><i class="fa fa-calendar-check-0
fa-fw w3-margin-right"> My Events</i></button>
<div id="Demo2" class="w3-hide w3-container">
<p>Some other text..</p>
</div>
<button onclick="myFunction('Demo3')" class="w3-button
w3-block w3-theme-l1 w3-left-align">
<i class="fa fa-user fa-fw w3-margin-right"> My Photos
</i></button>
<!-- class w3-container is used to hold the photos album layout -->
<!-- "My Photos" button! -->
<div id="Demo3" class="w3-hide w3-container">
<div class="w3-row-padding">
<br>
<!-- the following is where you put your photo album! -->
<!-- class w3-half is a grid layout as a two-column -->
<!-- layout relative to the class w3-container used -->
<!-- in the album layout so the photos are arranged -->
<!-- side by side as a two-column layout -->
<div class="w3-half">
<img src="./image/paul_tuon.jpg" style="width: 100%"
class="w3-margin-bottom">
</div>
<div class="w3-half">
<img src="./image/graduation.jpg" style="width: 100%"
class="w3-margin-bottom">
</div>
<!-- this is another two-column grid stacking below above -->
<div class="w3-half">
<img src="./image/paul_tuon.jpg" style="width: 100%"
class="w3-margin-bottom">
</div>
<div class="w3-half">
<img src="./image/graduation.jpg" style="width: 100%"
class="w3-margin-bottom">
</div>
<!-- this is another two-column grid stacking below above -->
<div class="w3-half">
<img src="image/example5.jpg" style="width: 100%"
class="w3-margin-bottom">
</div>
<div class="w3-half">
<img src="image/graduation.jpg" style="width: 100%"
class="w3-margin-bottom">
</div>
</div> <!-- end div class="w3-row-padding" -->
</div> <!-- end div id="Demo3" -->
</div> <!-- end div class="w3-white" -->
</div> <!-- end div class="w3-card w3-round" -->
<!-- this is the end of an accordion-like feature! -->
<!-- at this point there are still 3 open div -->
<!-- Interest: the miscellaneous content of interest! -->
<!-- w3-hide-small is to not display the content when mobile -->
<!-- device is used to load the web site! so "Interests" content -->
<!-- won't be loaded if mobile device is being used to load -->
<!-- this web site -->
<div class="w3-card w3-round w3-teal w3-hide-small">
<div class="w3-container">
<p>Interests</p>
<p>
<span class="w3-tag w3-small w3-theme-d5">News</span>
<span class="w3-tag w3-small w3-theme-d4">W3Schools</span>
<span class="w3-tag w3-small w3-theme-d3">Labels</span>
<span class="w3-tag w3-small w3-theme-d2">Games</span>
<span class="w3-tag w3-small w3-theme-d1">Friends</span>
<span class="w3-tag w3-small w3-theme">Games</span>
<span class="w3-tag w3-small w3-theme-l1">Friends</span>
<span class="w3-tag w3-small w3-theme-l2">Food</span>
<span class="w3-tag w3-small w3-theme-l3">Design</span>
<span class="w3-tag w3-small w3-theme-l4">Art</span>
<span class="w3-tag w3-small w3-theme-l5">Photos</span>
</p>
</div>
</div>
</div> <!-- end left column -->
<!-- at this point there are still 2 open <div> tags -->
<!-- start middle column -->
<div class="w3-col m7">
<!-- right here where I add some new content to the middle column -->
<!-- I add a scrolling message board to make it more flashy. for example: -->
<div class="w3-row-padding">
<!-- notice that you need to use the entire length of the grid: m12 -->
<!-- meaning the entire middle column -->
<div class="w3-col m12">
<div class="w3-card-2 w3-round w3-white">
<div class="w3-container w3-padding">
<marquee bgcolor=white width="100%" height="50">
<font size="5" color="#FF66FF">
Welcome to the 21st century and beyond where digital mobile rules!</font>
<font size="5" color="#1883FF">More content to scroll!</font>
</marquee>
</div>
</div>
</div>
</div>
<div class="w3-row-padding">
<div class="w3-col m12">
<div class="w3-card w3-round w3-white">
<div class="w3-container w3-padding">
<h6 class="w3-opacity">Social Media Template</h6>
<p contenteditable="true" class="w3-border
w3-padding">Status: Feeling blue!</p>
<button type="button" class="w3-button w3-theme">
<i class="fa fa-pencil"></i> Post
</button>
</div>
</div>
</div>
</div>
<div class="w3-container w3-card w3-round w3-blue w3-margin">
<img src="./image/paul_tuon.jpg" alt="Avatar" class="w3-left
w3-circle w3-margin-right" style="width:60px">
<span class="w3-right w3-opacity">1 min</span>
<h4>John Doe</h4>
<hr class="w3-clear">
<p>This is just an ordinary content! You can put whatever
content you want!</p>
<div class="w3-row-padding" style="margin:0 -16px">
<!--
<div class="w3-half">
<img src="./image/graduation.jpg" alt="just a picturer"
style="width: 100%" class="w3-margin-bottom">
</div>
<div class="w3-half">
<img src="./image/paul_tuon.jpg" alt="another picture"
style="width: 100%" class="w3-margin-bottom">
</div>
-->
</div>
<button type="button" class="w3-button w3-theme-d1 w3-margin-bottom">
<i class="fa fa-thumbs-up"></i> Like</button>
<button type="button" class="w3-button w3-theme-d2 w3-margin-bottom">
<i class="fa fa-comment"></i> Comment</button>
</div>
<div class="w3-container w3-card w3-round w3-khaki w3-margin"><br>
<!--
<img src="./image/graduation.jpg" alt="Avatar" class="w3-left
w3-circle w3-margin-right" style="width:60px">
-->
<span class="w3-right w3-opacity">16 min</span>
<h4>Jane Doe</h4>
<hr class="w3-clear">
<p>Lorem ipsum dolor. Lorem ipsum dolor. Lorem ipsum dolor.
Lorem ipsum dolor. Lorem ipsum dolor.</p>
<button type="button" class="w3-button w3-theme-d1 w3-margin-bottom">
<i class="fa fa-thumbs-up"></i> Like</button>
<button type="button" class="w3-button w3-theme-d2 w3-margin-bottom">
<i class="fa fa-comment"></i> Comment</button>
</div>
The following block of code contained in the original template
<!--
<div class="w3-container w3-card w3-round w3-lime w3-margin"><br>
<img src="./image/paul_tuon.jpg" alt="Avatar" class="w3-left
w3-circle w3-margin-right" style="width:60px">
<span class="w3-right w3-opacity">30 min</span>
<h4>Angie Jane
<hr class="w3-clear">
<img src="./image/gradution.jpg" class="w3-margin-bottom"
style="width:100%">
<p>Lorem ipsum dolor. Lorem ipsum dolor. Lorem ipsum dolor.
Lorem ipsum dolor. Lorem ipsum dolor.</p>
<button type="button" class="w3-button w3-theme-d1 w3-margin-bottom">
<i class="fa fa-thumbs-up"></i> Like</button>
<button type="button" class="w3-button w3-theme-d2 w3-margin-bottom">
<i class="fa fa-comment"></i> Comment</button>
</div>
-->
<!-- Accordion -->
<div class="mobile-card mobile-round">
<div class="mobile-pale-blue">
<button onclick="myFunction('group')"
class="mobile-button mobile-block mobile-theme-l1
mobile-left-align">
<i class="fa fa-circle-onotch fa-fw
mobile-margin-right"> My Groups</i>
</button>
<div id="group" class="mobile-hide mobile-container">
<p>Some text..</p>
</div>
<button onclick="accordion('event')"
class="mobile-button mobile-block mobile-theme-l1
mobile-left-align">
<i class="fa fa-calendar-check-0 fa-fw
mobile-margin-right"> My Events</i>
</button>
<div id="event" class="mobile-hide mobile-container">
<p>Some other text..</p>
<div>
<span class="hljs-string"><button onclick="accordion('photo')"
class="mobile-button mobile-block mobile-theme-l1
mobile-left-align"><i class="fa fa-user
fa-fw mobile-margin-right"> My Photos</i>
</button>
<div id="photo" class="mobile-hide mobile-container">
<div class="mobile-row-padding">
<br>
<div class="mobile-half">
<img src="./image/paul_tuon.jpg" style="width: 100%"
class="mobile-margin-bottom">
</div>
<div class="mobile-half">
<img src="./image/paul_tuon_graduation.jpg"
style="width: 100%" class="mobile-margin-bottom">
</div>
<div class="mobile-half">
<img src="./image/paul_tuon.jpg"
style="width: 100%" class="mobile-margin-bottom">
</div>
<div class="mobile-half">
<img src="./image/paul_tuon_graduation.jpg"
style="width: 100%" class="mobile-margin-bottom">
</div>
<div class="mobile-half">
<img src="image/paul_tuon.jpg"
style="width: 100%" class="mobile-margin-bottom">
</div>
<div class="mobile-half">
<img src="image/paul_tuon_graduation.jpg"
style="width: 100%" class="mobile-margin-bottom">
</div>
</div> <!-- end div class="mobile-row-padding" -->
</div> <!-- end div id="photo" -->
</div> <!-- end div class="mobile-pale-blue" -->
</div> <!-- end div class="mobile-card mobile-round" -->
<!-- end accordion style feature! -->
</div> <!-- end middle column -->
<!-- start right column -->
<!-- here it is: right column is 2/12 of the grid -->
<div class="w3-col m2">
<div class="w3-card w3-round w3-aqua w3-center">
<div class="w3-container">
<p>Upcoming Events:</p>
<img src="./image/image_105.jpg" class="w3-margin-bottom"
style="width:100%">
<p><strong>Holiday</strong></p>
<p>Friday 15:00</p>
<p><button type="button" class="w3-button w3-theme-14
w3-block">Info</button></p>
</div>
</div>
<div class="w3-card w3-round w3-pink w3-center">
<iv class="w3-container">
<p>Friend Request</p>
<!--
<img src="./image/graduation.jpg" class="w3-margin-bottom"
style="width:50%">
-->
<span>Jane Doe</span>
<div class="w3-row w3-opacity">
<div class="w3-half">
<button type="button" class="w3-button w3-block-14
w3-green w3-section" title="Accept">
<i class="fa fa-check"></i></button>
</div>
<div class="w3-half">
<button type="button" class="w3-button w3-block-14
w3-red w3-section" title="Decline">
<i class="fa fa-remove"></i></button>
</div>
</div>
</div>
</div>
<br>
<div class="w3-card w3-round w3-purple w3-padding w3-center">
<p>ADS</p>
</div>
<br>
</div> <!-- end right column -->
<!-- here is the closing div for class w3-row! -->
</div> <!-- end grid containing class w3-row -->
<!-- here is the closing div that contains class w3-container! -->
</div> <!-- end page container -->
<!-- here is the last section of the website: footer -->
<!-- start footer -->
<footer class="w3-container w3-theme-d3 w3-padding-16">
<div>Follow us on social medias: Facebook, Twitter, Instagram!</div>
<div class="w3-right">Contact: john@doe.com</div>
</footer>
<script>
// Accordion
function myFunction(id)
{
var x = document.getElementById(id);
if (x.className.indexOf("w3-show") == -1)
{
x.className += " w3-show";
x.previousElementSibling.className += " w3-theme-d1";
}
else
{
x.className = x.className.replace("w3-show", "");
x.previousElementSibling.className =
x.previousElementSibling.className.replace(" w3-theme-d1", "");
}
}
// used to toggle on smaller screen when clicking on the menu button
function openNav()
{
var x = document.getElementById("navDemo");
if (x.className.indexOf("w3-show") == -1)
{
x.className += " w3-show";
}
else
{
x.className = x.className.replace(" w3-show", "");
}
}
</script>
</body>
</html>
/* there you have it! */
/* a responsive mobile image slider */
/* when the website is loaded using a mobile */
/* device the slider showing one image sliding */
/* at a time! */
/* again, check out the plugin website mentioned earlier */
/* to find all kinds of plugins to use on your website! */
b
/* go at it! */
Fontawesome is a collection of ready-made images available to anyone for free. For a visual view on some examples of fontawesome images, go to my other website called "MondayThruSunday.COM," and look in all of the menu items and there should be a fontawesome in the front of the menu name for each menu item.
For example, for a menu name called "Home," there is a fontawesome image looking like a house in the front of the word "Home"; for a menu name called "Search," there is a fontawesome image looking like a magnifying glass in the front of the word "Search"; for a menu name called "Signup," there is a fontawesome image looking like three horizontal hash bars in the front of the word "Signup."
Fontawesomes are easy to use and most of all, you don't need to download them from somewhere and install them on your computer. They are available via the browser technology and the HTML.
To use fontawesomes, all you have to do is include the link to a CDN and then referring to its name as a class name inside your HTML element document -- the same way you refer to your CSS class names. See an illustration below.
Fontawesome images class starts with the word "fa fa-." For examples:
In the head <head> section of your HTML file, include the below link:
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css">
Again, a CDN (or Content Delivery Network) is just a central data
network that mainly delivering data content to users via a link!
Note that there are hundreds of CDNs out there that you can link to.
The above link is just one of those. Google has one and so does Bootstrap.
Here is a CDN from Bootstrap:
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
So it is just a matter of preference of which CDN to use and all will work just fine!
After you included the link, you can refer to the font awesome images as
you normally would the same way you refer to a CSS class. For example:
In the body <body> section of your HTML file, do this:
<div class="fa fa-home"></div> will display an image of a house:
<div class="fa fa-home"> Home</div> will display: Home
<div class="fa fa-bars"></div> will display an image of three horizontal hash bars:
<div class="fa fa-search"></div> will display an image of a magnifying glass:
<div class="fa fa-check"></div> will display an image of a checkmark:
<div class="fa fa-globe"></div> will display an image of a globe:
<div class="fa fa-cart-arrow-down"></div> will display an image of a shopping cart:
<div class="fa fa-plus"></div> will display an image of a plus sign:
There are thousands of fontawesome images available on the Internet for free to use. Just Google the term "fontawesome" and it will give a lot of results to choose from.
Earlier, I mentioned that you don't need to download fontawesome images anywhere from the Internet. That is true for the standard fontawesome images that are provided by the World Wide Web consortium.
However, for thousands of specialized third party fontawesome images like specialized shopping cart [where you can customize the inter-activity of the cart] and others, you need to download them from the Internet and store them in your folders and refer to them accordingly.
All CDNs do the same thing: they gather all of the fontawesome images and store them in a directory on their server and provide a link to the public to link to.
For more about fontawesome tutorials, please check out this site: https://www.w3schools.com/css/css_icons.asp
Here is another excellent fontawesome tutorial: https://www.w3resource.com/icon/font-awesome/web-application-icons/cart-arrow-down.php
Here is the official site of the standard fontawesome consortium site: https://fontawesome.com/icons/cart-arrow-down
Here is the official site of the standard fontawesome consortium site that lists a fontawesome cheat sheet that you can basically find a particular fontawesome image quickly: https://fontawesome.com/cheatsheet?from=io
Here is an interesting topic that you might find very useful: CSS Badge
/** showing the number of items in the cart **/
/** here, assuming you have a shopping cart that has a **/
/** variable called $cart_count that holds the number of **/
/** items in the cart **/
cart<a href="#"><span class="badge" id="cart-count"><?=$cart_count?></span></a>
For more tutorial on "badge" please click on the link below!
As mentioned earlier multiple times, the best place to advance your programming skills is the W3Schools. One of the many topics that you might want to spend some time on learning is the "dialog modal" box tutorial that can be found here: https://www.w3schools.com/bootstrap/bootstrap_modal.asp. With the modal dialog box, you can put all kinds of content to make your users interact with it.
Here are some of the interesting topics that you might want to spend some time learning:
https://www.w3schools.com/bootstrap/bootstrap_carousel.asp https://www.w3schools.com/bootstrap/bootstrap_affix.asp https://www.w3schools.com/bootstrap/bootstrap_glyphicons.asp https://www.w3schools.com/bootstrap/bootstrap_pagination.asp https://www.w3schools.com/bootstrap/bootstrap_images.asp https://www.w3schools.com/css/css_image_gallery.asp https://www.w3schools.com/css/css3_text_effects.asp https://www.w3schools.com/html/html_entities.asp
So there are lots of topics available for you to improve your programming skills. So go at it!!!
When you program websites, you might run into situations that require you to be creative instead of using CSS to accomplish your tasks. One of the neat trick is to use non-breaking space command or to put some spaces between your content, as the "<marquee></marquee>" example below shows.
One is approximately equals to 10 pixels. As you can see in the example below, it requires a lot of to make the spaces wide enough.
The drawback of using instead of CSS is that it is very cluttered and messy; however, it is much quicker and easier than having to write CSS definitions.
Sometimes you can't write CSS definitions to fit your goal as in my case below. So you are left to use to accomplish the task.
Nonetheless, be very careful using instead of CSS because in mobile devices it might not display very well, especially if you have lots of .
So use it sparingly is the best way to use it. Don't over-use it!
In my case, it works very well on any mobile devices.
So there you have it! A very neat trick to use!!!
Here is a very simple trick to make your website looks awesome.
You won't see this trick anywhere in the document or tutorials
anywhere but only right here from me.
I use this trick on my own websites on a regular basis.
Here it is:
<div style="width: 700px; height: auto; background-color: #ffdddd;
padding: 5px 5px 5px 5px"><marquee>Content to scroll!</marquee>
</div>
The tag is called "<marquee></marquee>"
This simple tag scrolls continuously any content you put in it!
You can put this "<marquee></marquee>" tag anywhere as a
standalone or inside any HTML elements: <div>, <span>, <p>, etc.
You can also style your <marquee> content, such as
configuring the width and height and background color, etc.
Here is the same code that I use on my website: ZeroNilZilch.COM.
Notice that I embedded the styling code directly in the <marquee></marquee> as
appose to putting it in the <div></div> or other HTML elements.
It is just a personal preference and any HTML elements will work just fine.
As you can see, I had to use lots of to make enough spaces between contents!
The listing of between contents is a continuous line, but here,
it is broken down into multiple lines for displaying purpose!
<marquee bgcolor="white" width="100%" height="50">
<font size="5" color="#00FF99">www.ZeroNilZilch.COM</font>
<font size="5" color="#3333FF">Where the future is already here!</font>
<font size="5" color="#00FFFF">Explore, see the horizon,
open your mind and let your curiosity run wild,
discover, inspire and enrich your learning!!!</font>
<font size="5" color="#3333FF">The engine of your inginuity is limited only to
your imagination!!!</font>
<font size="5" color="#FF66FF">
Welcome to the 21st century and beyond where digital mobile rules!</font>
<font size="5" color="#1883FF">
This website and all of our affiliate sites are mobile-friendly!</font>
<font size="5" color="#00FFFF">
This means that you can use your mobile phones or any portable
small device to surf and shop with us conveniently and securely at all of our
affiliate sites!!!</font>
<font size="5" color="#FF66FF">They're built for the Millenials,
where all things Millenial, the Millenials' way!!</font>
<font size="5" color="#3333FF">Go ahead and fire up your smartphones and load
this website and see if it's mobile-friendly or not!</font>
</marquee>
Here are some more special characters to make your websites appear more useful. Please check this out:
Here is a very simple trick to make your texts appear vertically as well as other text effects that you might find useful. Please check these out:
https://www.w3schools.com/cssref/css3_pr_writing-mode.asp https://www.w3schools.com/css/css_align.asp https://www.w3schools.com/cssref/pr_text_text-decoration.asp https://www.w3schools.com/cssref/css3_pr_transform.asp https://www.w3schools.com/cssref/css3_pr_transition.asp https://www.w3schools.com/cssref/tryit.asp?filename=trycss_zindex
Here is a very simple trick to make your navigation bar works on mobile devices. On desktop it will display the menu items horizontally but on mobile devices, it will display them vertically.
Note that on mobile devices, the menu bar will be cleared all of menu items and a fontawesome fa fa-bars: is used instead in place of the menu items and the fa fa-bars is shown on the menu bar as a button to click.
When a user clicks on the fa fa-bars symbol it opens up the menu items listing the menu items vertically and neatly.
Using NAV tag, you don't need to do any special tricks to make it mobile-friendly: it is already built-in the browser technology.Just list your menu items to make it work on desktop devices as you normally would and the browser technology takes care of the mobile devices display behind the scene for you so that you don't need to do any special tricks:
https://www.w3schools.com/tags/tag_nav.aspThere you have it! A secret way to beautify your website!!!
Here is a very simple trick to make your website mobile-friendly. First of all, this is just a simple trick that is suited to some small situations where CSS is too complicated and too bulky to use. This trick works very well when you have a section of the code needs to handle small mobile devices and another section next to it can be used for desktop devices. For example:
<?php
/** this is a special trick that you'll never see from **/
/** any documentation or tutorials anywhere, period! **/
/** here is the special trick using a combination of PHP and Javascript: **/
echo "<script language='javascript'>
/** you need a space between the echo " and location **/
echo " location.href=\"${_SERVER['SCRIPT_NAME']}?${_SERVER['QUERY_STRING']}"
. "&width=\" + screen.width + \"&height=\" + screen.height;\n";
echo "</script>\n";
/** basically, the code above picks out the width and height **/
/** of the device using Javascript screen object and just **/
/** referring to the object's property: width and height! **/
/** very neat and simple! **/
/** the reference to 'location.href' is just reading the url's **/
/** incoming request and picking off the querystring at **/
/** the same time! **/
/** okay, let's see how it works! **/
/** first, you test the size of the device **/
/** in other words, when the browser hits this code above, **/
/** it checks to see what size the device is. **/
/** if it is a desktop device being used to surf this website, **/
/** it will execute the area of the code designed to be used on desktop! **/
/** if it is a mobile device being used to surf this website, **/
/** it will execute the area of the code designed to be used on mobile **/
/** devices **/
/** this is much simpler than having to write CSS definitions **/
/** it works just as good as if you had written a CSS definition to **/
/** do the job! **/
/** as a matter of fact, the groups that wrote the CSS rules to **/
/** make CSS definitions mobile-friendly used this same technique to **/
/** detect the devices to make their CSS rule do the job **/
/** of detecting the various mobile size! **/
/** they called it media definition that looks like this: **/
@media (max-width: 480px)
{
.nav-collapse
{
-webkit-transform: translate3d(0, 0, 0);
}
.page-header h1 small
{
display: block;
line-height: 20px;
}
}
/** but first, you need to test if the browser can read **/
/** the dimensions of the device being used to surf the webpage! **/
/** all browsers returns a width and height of the device being **/
/** used every time it loads the webpage! **/
/** but we need to use a special trick that you'll never see from **/
/** any documentation or tutorials anywhere, period! **/
/** here is a special trick using a combination of PHP and Javascript: **/
<?php
if (isset($_GET['width']) AND isset($_GET['height']))
{
global $width;
global $height;
// grab the geometry variables
$width = $_GET['width'];
$height = $_GET['height'];
if ($width > 600)
{
// desktop device! prepare code to be used on desktop!
?>
<!-- left column -->
<div class="mobile-col m3">
<!-- display left column content for desktop! -->
</div>
<!-- end left column -->
<!-- middle column -->
<div class="mobile-col m7">
<!-- display middle column content for desktop! -->
</div>
<!-- end middle column -->
<!-- right column -->
<div class="mobile-col m2">
<!-- display right column content for desktop! -->
</div>
<!-- end right column -->
<?php
} // end if $width > 600
else
{
// mobile devices! prepare code to be used on mobile devices!
// notice that inside this mobile section, you still need to
// use CSS to style the content to be mobile-friendly!
// I told you earlier that this simple trick doesn't do all of
// your mobile-friendly works! it does for certain situations only!
// you can use both this trick and CSS definitions to your advantage!
?>
<!-- left column -->
<div class="mobile-col m3">
<!-- display left column content for desktop! -->
</div>
<!-- end left column -->
<!-- middle column -->
<div class="mobile-col m7">
<!-- display middle column content for desktop! -->
</div>
<!-- end middle column -->
<!-- right column -->
<div class="mobile-col m2">
<!-- display right column content for desktop! -->
</div>
<!-- end right column -->
<?php
} // end else if $width > 600
} // end if (isset($_GET['width']) AND isset($_GET['height']))
else
{
// pass the geometry variables (preserve the original query string
echo "<script language='javascript'>\n";
echo " location.href=\"${_SERVER['SCRIPT_NAME']}?${_SERVER['QUERY_STRING']}"
. "&width=\" + screen.width + \"&height=\" + screen.height;\n";
echo "</script>\n";
// if for some reasons that the browser fails to grab the dimensions
// it will come here and you can handle that case accordingly!
// that situation is very rare! this code above always returns
// the dimensions!
// desktop device! prepare code to be used on desktop!
?>
<!-- left column -->
<div class="mobile-col m3">
<!-- display left column content for desktop! -->
</div>
<!-- end left column --<
<!-- middle column -->
<div class="mobile-col m7">
<!-- display middle column content for desktop! -->
</div>
<!-- end middle column -->
<!-- right column -->
<div class="mobile-col m2">
<!-- display right column content for desktop! -->
</div>
<!-- end right column -->
<?php
}
?>
There you have it!
p>A secret way to beautify your website by making it mobile-friendly!!!Here is an interesting topic that you might find very useful: Tracking Visitors of Your Website
You can write your own simple cookies code to capture your website visitors or use the professionally-made tools and here are a few to choose from.
If you want to write your own simple cookies code to capture your website visitors, check the following out:
Create A Simple PageView Counter Using PHP and MySQL
Seriously? Really? The code above was being written in the year 2020? Am I seeing it right?
The old MySQL API was deprecated in the year 2015 and the code above was being written in the year 2020?
Amazingly, even the code was being written in May 2020 and the author still uses the old MySQL API that has been deprecated a long time ago and it has no longer in used ever since.
Anyhow, to correct the problem, you need to rewrite the connection code in PDO. For a brief tutorial, see my other tutorial called "Introduction to PDO."
Here is a partial code found in the tutorial listed above that needs to be rewritten:
// the author is using a localhost for building and testing // so you need to replace the db connection values accordingly // when migrating to a "live" web hosting $host = "localhost"; $username = "root"; $password = ""; $databasename = "sample"; $connect = mysql_connect($host, $username, $password); $db = mysql_select_db($databasename); // change the two lines above to the following: $connect = new PDO(mysql:host=$host;dbname=$databasename", $username, $password);
So look for a code fragment that says:
$check_ip = mysql_query("select userip from pageview where page='yourpage' and userip='$user_ip'"); if (mysql_num_rows($check_ip)>=1) { } else { $insertview = mysql_query("insert into pageview values('','yourpage','$user_ip')"); $updateview = mysql_query("update totalview set totalvisit = totalvisit+1 where page='yourpage' "); }
Modify the above code to look like the following:
try { $sql = $connect->prepare("SELECT userip FROM pageview WHERE page = ':yourpage' AND userip = ':user_ip'"); $check_ip = $sql->execute(array($yourpage, $user_ip)); } catch (PDOException $e) { echo 'ERROR: Cannot retrieve data. ' . $e->getMessage(); } if ($check_ip) { // found view counts and do nothing! } else { // try to insert another visitor/pageview to the database try { $sql = $connect->prepare("INSERT INTO pageview VALUES (?, ?)"); $insertview = $sql->execute(array('page' => $yourpage, 'userip' => $user_ip)); } catch (PDOException $e) { echo 'ERROR: Cannot insert data. ' . $e->getMessage(); } // also try to update visitor/pageview try { $totalvisit++; $sql = $connect->prepare("UPDATE totalview SET totalvisit = ? WHERE page = ? "); $updateview = $sql->execute(array($totalvisit, $yourpage)); } catch (PDOException $e) { echo 'ERROR: Cannot update data. ' . $e->getMessage(); } // Change the following code accordingly: <body> <?php // Use a SELECT query similar to the one shown above! $stmt = mysql_query("select totalvisit from totalview where page='yourpage' "); // The one line below can be replaced by the result from the SELECT query above! // Just put: echo $stmt . 'times.' ?> <p>This page is viewed <?php echo mysql_num_rows($stmt);?> times.</p> </body>
The tutorial above mentioned a variable called $yourpage, which the author didn't explain how to get it. Here is how you assign value to variable $yourpage:
// take all of the following code beginning with the $protocol line and all the
// way to the end at the "$yourpage" line and place them at the top of the
// code example above right before the line that says: $host = "localhost";
// protocol = http or https
$protocol = stripos($_SERVER['SERVER_PROTOCOL'], 'https') === 0 ? 'https://' : 'http://';
// so instead of the above shortcut/simpler protocol code, you can use this much
// more robust and complete protocol code (by uncommenting the following three lines):
// $protocol = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') ||
// $_SERVER['SERVER_PORT'] == 443 ||
// $_SERVER['HTTP_X_FORWARDED_PORT'] == 443) ? "https://" : "http://"
// if you uncomment the three lines above, remove the below port statement completely
// and also take out the variable $port in the $yourpage line (below) as well!
// or if you use the shortcut/simpler protocol code above, you can take out the
// variable $port below as well and it will work just fine!
// in both cases, including port is just not necessary as the computer already
// knows what port it is running on.
// so omitting port entirely will work just fine!
// for beginners, I suggest that you omit the port option to avoid specifying the
// wrong port and perhaps causing problems!
$port = ($_SERVER["SERVER_PORT"] == "80") ? "" : (":" . $_SERVER["SERVER_PORT"]);
$yourpage = $protocol .
$_SERVER['SERVER_NAME'] . $port . $_SERVER['REQUEST_URI'];
As you can see, now $yourpage contains your actual page. Put the whole code in every page that you want to track. When a visitor visits a page that contains the (whole) code it will execute the whole code and therefore captures visitor's information and saves visitor's information in the database.
As you may well aware, the author of the tutorial above didn't do a good job explaining and didn't even finish the tutorial. It's a complete disaster! I'm not about to finish someone else's tutorial; and therefore, leaving it to you to judge on your own and maybe finish the job yourself. Good luck!
The next one is much better! Try it!
PHP Program to count Page Views
Build a Visitor Tracking System for your Website with PHP
How To Track Visitor IP, Visited Page, Visiting Time Using PHP
What is the best way to track visitors?
If you use the last list code example above from GeekLabel.COM, there is a minor typo in the code and it won't work as intended. So look for a code fragment that says:
else if (!isset($HTTP_USER_AGENT)) { $HTTP_USER_AGENT = ''; }
Remove the else clause so that it reads:
if (!isset($HTTP_USER_AGENT)) { $HTTP_USER_AGENT = ''; }
Now the code should work as intended.
The code above uses the old MySQL API that is deprecated and no longer in used. You need to rewrite the connection code in PDO. For a brief tutorial, see my other tutorial called "Introduction to PDO."
Here is a partial code that needs to be rewritten:
// you need to replace the db connection values accordingly $hostname_visitors = "host"; $database_visitors = "database"; $username_visitors = "username"; $password_visitors = "password"; $visitors = new PDO(mysql:host=$hostname_visitors;dbname=$database_visitors", $username_visitors, $password_visitors);
So look for a code fragment that says:
//write the required data to database mysql_select_db($database_visitors, $visitors); $sql = "INSERT INTO visitors_table (visitor_ip, visitor_browser, visitor_hour, visitor_minute, visitor_date, visitor_day, visitor_month, visitor_year, visitor_refferer, visitor_page) VALUES ('$visitor_ip', '$visitor_browser', '$visitor_hour', '$visitor_minute', '$visitor_date', '$visitor_day', '$visitor_month', '$visitor_year', '$visitor_refferer', '$visitor_page')"; $result = mysql_query($sql) or trigger_error(mysql_error(),E_USER_ERROR);
Modify the code so that it reads:
//write the required data to database $sql = $visitors->prepare("INSERT INTO visitors_table (visitor_ip, visitor_browser, visitor_hour, visitor_minute, visitor_date, visitor_day, visitor_month, visitor_year, visitor_refferer, visitor_page) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; $result = $sql->execute(array('visitor_ip' => $visitor_ip, 'visitor_browser' => $visitor_browser, 'visitor_hour' => $visitor_hour', // Typo: remove the ' at the end 'visitor_minute' => $visitor_minute', // Typo: remove the ' at the end 'visitor_date' => $visitor_date', 'visitor_day' => $visitor_day', 'visitor_month' => $visitor_month', 'visitor_year' => $visitor_year', 'visitor_refferer' => $visitor_refferer', 'visitor_page' => $visited_page')); // Typo: $visited_page and NOT $visitor_page if (!$result) { echo 'Cannot insert data into database.'; }
Look for the next code fragments that say: $additionalQuery = "SQL_CALC_FOUND_ROWS " and mysql_select_db($database_visitors, $visitors) and remove them both entirely.
Of course, you need to modify the rest of the old MySQL code accordingly, including this fragment: $query_visitors = "(SELECT ".$additionalQuery." * FROM visitors_table WHERE" to SELECT count(*) FROM visitors_table WHERE".
Pay special attention to the function called selfURL() because it returns the page of your website that the visitors visited. You would want to know exactly what page your visitors visited on your website and this function gives you that information. There is a typo that says: 'visitor_page' => $visitor_page' and it should be corrected to 'visitor_page' => $visited_page.
There are also lots of typos that says: 'visitor_page' => $visitor_page' and the oppostrophe at the end should be removed to be 'visitor_page' => $visited_page.
If you want to use the professionally-made tools and here are a few to choose from:
Paid Web Analytics Tools For Tracking Your Visitors
Web Analytics Tools For Tracking Your Visitors
10 Web Analytics Tools For Tracking Your Visitors
Here is my "barebone" simple code to track your visitors visiting on the index.php front page of your website. Any time a visitor visits your website, which is primarily being visited on the index.php front page, it tracks that person as one visit. If that person returns to visit your website again on another occassion on another session, it accounts for that visit as another one visit as well.
In other words, it logs each visit by a person as one visit no matter how many pages or area a visitor is visiting because this "barebone" simple code is designed to track only one page, which is the index.php front page. When a person continues to visit other pages on your website it does not account for those visits.
When a person leaves the website entirely and comes back to visit the website again, it again will log that person as one unique visit without differentiating the visit as a return visit. It keeps doing this for all other visitors as well.
It tallies all of the visits from all visitors [new or old visitors] that enter the website on every session to account for the website traffic. The total count of the page hits does not account for the return visits by the same person.
You can make improvement to this code as well or use it "AS IS" without any modification.
First of all, you will need to create a MySQL database to store all of your page hits.
To track your website traffic, just put all of the below code in a PHP file (perhaps, name it as pagehit.php) and then include this file name (pagehit.php) at the top of your index.php front page. See an example index.php front page later.
Remember that the following code is written to log only one page, which is assumed to be an index.php front page. So put the whole code below at the top of your index.php front page.
However, you can track page hits on every page of your website as well -- not just the index.php front page.
To count page hits on all of your website pages, just include this file name (pagehit.php) in every one of your pages. It will log different querystrings for different pages.
So the key thing to come away with this code (below) is that you can place the below code at the top of every page of your website if you want to track each page. However, it will distort your total page hits because a visitor may visits all of your pages and since each of your page contains a code to capture the page hit, the total page hit will be larger than it should be.
Let's put it this way: You want to track your website's unique traffic but if a visitor visits all of your pages or just some of your pages, the page hits will not reflect the true website's unique traffic. That's why this code below was designed to track only the index.php front page so that it accurately tracks the website's unique traffic.
So if you put the below code at the top of every page on your website it will just add all of the page hits together from all of your pages, including the index.php front page. In other words, it combines all of the page hits from all of your pages as one total and this total does not reflect the true unique traffic of the site.
So if you want to know which page got how many hits, you'll have to modify the code slightly because the code below just lump all of the various page hits together as one total, and this total includes the hits on the index.php front page, too.
Notice that you can either put the following code in a PHP file (pagehit.php) and include it like [include("pagehit.php")] in every page of your website OR just copy and paste the entire code and put it at the top of every page of your website and it will work just fine.
File: pagehit.php
<?php
/**
* a function to count how many times visitors visit a particular page
*
* you can call this function by passing a page file to it
*
* see at the bottom of this function to see how it is being called
*
* notice that argument $page can be any page on your website, but
* the database code just add all of the page hits together regardless
* of what page or pages you pass to it!
*
* this is where you can modify the database code slightly to store
* the different page hits individually! it's up to you to modify it!
*
* if you don't really care which page gets the most hit and only
* care about the whole website's total hit, then there is no need to
* modify this code! just use it "AS IS" and include the file
* pagehit.php at the top of the index.php front page and don't
* include this file in any of your pages because the index.php file
* is the only file we're tracking! nothing else!
*/
public function pageCounter($page, $referer)
{
// you might want to pass these connection parameters
// from external source instead of embedding them like here!
$hostingserver = 'root';
$databaseName = 'your_database_name';
$username = ''; // your database username
$password = ''; // your database password
// try to create a PDO connection instance
try
{
$conn = new PDO("mysql:host=$hostingserver;dbname=$databaseName",
$username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (PDOException $e)
{
echo 'Cannot connect to the PDO database. ' . $e->getMessage();
}
// now try to create a table named pagecounter if it
// doesn't already exist in the database
// if it already exists in the database, it will skip this try/catch blocks!
// in other words, it won't create a table named `pagecounter` because
// it already exists in the database!
// however, it will continue executing all codes following the try/catch
// blocks!
// FYI:
// I've found that for some shared hosting's PDO engine doesn't
// recorgnize this statement:
// 'CREATE TABLE IF NOT EXISTS'
// to solve that problem, remove the below statement and create the table
// manually using PHPmyAdmin or some other means!
// so you don't actually need to test this condition (below) every time a
// page is hit! in other words, you don't need to check if the table
// exists or not, because you already know that a table already have been
// created; and therefore, there is no need to use the condition
// code below!
// just remove the create table condition below and make sure your table
// have been created already and it will work just fine!
try
{
$sql = $conn->prepare("CREATE TABLE IF NOT EXISTS `pagecounter`
(
`id` int(25) NOT NULL auto_increment,
`page_name` varchar(255) NOT NULL default '',
`referer` varchar(255) NULL default '',
`page_hit` int(25) NOT NULL default '0',
`date_time` datetime NOT NULL default
CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) TYPE=MyISAM"
);
// execute the query to create the table
$sql->execute();
}
catch (PDOException $e)
{
echo 'Cannot create table pagecounter. ' . $e->getMessage();
}
// after creating the table, it's time to insert new page hits
// but first, check to see if there are any page hits already stored
// in the database
$query = $conn->prepare("SELECT * FROM pagecounter
WHERE page_name = :page");
$result = $query->execute(['page' => $page]);
// check to see if there are any page hits already stored
// in the database
if ($result)
{
// yes, there are page hits already stored in the
// database!
$result->setFetchMode(PDO::FETCH_ASSOC);
while ($row = $result->fetch())
{
// so just add the new page hit to the total
$counter = $row['page_hit'] + 1;
}
// after adding a new page hit to the total,
// we need to update the total page hits and as well as
// updating the rest of the record, too!
$update = $conn->prepare("UPDATE pagecounter
SET page_name = :page,
referer = :referer,
page_hit = :counter");
$update->execute([':page' => $page,
':referer' => $referer,
':counter' => $counter
]
);
}
else
{
// this must be for the first page hit!
// there are no page hit stored in the database,
// so we need to store the first page hit in the database
$stmt = $conn->prepare("INSERT INTO pagecounter
VALUES (?, ?, ?)"
);
$stmt->execute([
'page_name' => $page,
'referer' => $referer,
// since there are no page hits stored in the
// database, so it must be the first time,
// and therefore, 'page_hit' is set to 1
'page_hit' => '1'
]
);
// if you observe the create table code definition
// and the insert table code above, you'll notice that
// there are 5 table fields in the create table code
// while only 3 fields (page_name, referer, and page_hit) are
// performed in the insert/update table code above.
// if you look closely in the create table definition
// you'll notice that the 'id' field contains the
// "auto_increment" clause that MySQL uses to increment
// this 'id' automatically starting with number 1 and
// increments it by 1 each time you insert a row of record.
// therefore, the 'id' field is not directly handled by
// programmers -- it is handled by MySQL automatically.
// likewise, the `date_time` field is not directly handled by
// programmers, either -- it is handled by MySQL automatically,
// because it was declared in the definition to use a
// 'default' date time value, generating a date and time
// automatically every time an insert or an update operation
// is taking place.
// the function CURRENT_TIMESTAMP generates the date and time
// automatically!
// so it looks like this:
// `date_time` datetime NOT NULL default CURRENT_TIMESTAMP
// self-explanatory!
// now on to the code flow:
// since this is the first time a visitor saw this
// page, we initialize the page to one hit!
// the next time any visitor visits this page it
// will not come here in the "else" condition because
// $result contains some value(s) for the tracking page!
$counter = 1;
}
// return the result of the query back to the caller!
// this is the number of times the page has been hit by visitors!
return $counter;
} // end function pageCounter($page, $referer)
/**
* now that the function has been written, we can call that function
* from anywhere!
*
* to call that function, you have to include the following snippet
* of code!
*
* put the following code at the top of every page you want to track!
*/
// HTTP headers
// every time the Web runs it fires off the HTTP protocol and PHP has a
// a built-in variable called $_SERVER to grab all of the HTTP headers.
// The superglobal array variable $_SERVER has 32 values, i.e.,
// $_SERVER['REMOTE_ADDR'], $_SERVER['HTTP_REFERER'], $_SERVER['SERVER_NAME'],
// $_SERVER['QUERY_STRING'], $_SERVER['SCRIPT_NAME'], $_SERVER['PHP_SELF'],
// $_SERVER['IP_ADDRESS'], $_SERVER['DNT'], etc.
// and you can view these values by running in your view (index.php)
// page or in any page output code like this:
// print_r($_SERVER);
// here, we grab the page's url using the HTTP protocol,
// particularly the built-in (superglobal) array variable $_SERVER.
// in here, we're just grabbing those HTTP headers, such as the URI or URL,
// including the querystrings. that's what the following code is doing!
// the $_SERVER['PHP_SELF'] code is to refer to the current file itself!
// so if you put $_SERVER['PHP_SELF'] inside a file called index.php, it
// will run that file!
// as for $_SERVER['SERVER_NAME'] is to grab the server name, i.e.,
// example.com.
// as for $_SERVER['HTTP_REFERER'] is to grab the url that the visitor
// just came from!
// for example, if a visitor came to your website from another website
// called http://www.example.com, $_SERVER['HTTP_REFERER'] returns
// http://www.example.com
// as for $_SERVER['QUERY_STRING'] is to grab the url's querystring, the
// string after the '?', i.e.,
// www.example.com/?arg1=value1&arg2=value2&arg3=value3
// so this will look something like these:
// www.example.com/index.php?arg1=value1&arg2=value2&arg3=value3
// www.example.com/catalog.php?arg1=value1&arg2=value2&arg3=value3
// www.example.com/affiliate.php?arg1=value1&arg2=value2&arg3=value3
// www.example.com/mypage.php?arg1=value1&arg2=value2&arg3=value3
/**
* here are some useful items you might find useful:
*
* $visitor_hour = date("h");
* $visitor_minute = date("i");
* $visitor_day = date("d");
* $visitor_month = date("m");
* $visitor_year = date("y");
*/
$self_url = $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'] . '?' .
$_SERVER['QUERY_STRING'];
// grab the url of the visitor's last link!
$referer = $_SERVER['HTTP_REFERER'];
// we call pageCounter() and getting a page hit instantly
$page_hit = pageCounter($self_url, $referer);
/**
* now that we have a page hit we can do whatever we want, such as
* display it somewhere on the same page. how you use this page hit
* is up to you, but here we just echoing out to the browser to
* display the page hit on the same page!
*/
echo $page_hit;
/**
* what if you want to put the display of the page hit somewhere
* on your website beside the default front index.php page?
*
* in other words, you want to put a hit counter in a different page
* other than the front index.php.
*
* in that case, you have to query the database using the code
* similar to the following. see a seperate index.php example below.
*
* you need to put this code at the very top of your xxx.php page!
*
* // try to create a PDO connection instance
* try
* {
* $conn = new PDO("mysql:host=$hostingserver;dbname=$databaseName",
* $username, $password);
* $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
* }
* catch (PDOException $e)
* {
* echo 'Cannot connect to the PDO database. ' . $e->getMessage();
* }
*
* $query = $conn->prepare("SELECT * FROM pagecounter
* WHERE page_name = :page");
*
* $result = $query->execute('page' => $page);
*
* if ($result)
* {
* $result->setFetchMode(PDO::FETCH_ASSOC);
* while ($row = $result->fetch())
* {
* $counter = $row['page_hit'] + 1;
* }
* }
*
* and then you can basically display the hit page anywhere on
* your xxx.php. for example:
*
* <p>Total visits: <?=$counter?>
*
* see the "barebone" index.php page below as an example!
*/
?>
The example above can be used to display in the "barebone" index.php front page as well.
Here is a "barebone" index.php front page example to show how to include the pagehit.php file at the top of your index.php front page.
File: index.php
?<php
// here, assuming you name the whole code above as pagehit.php
// this is it! just one line!
// very simple to include a tracking script on
// your index.php front page!
// don't forget to put the file pagehit.php at the same level
// in directory as your index.php
include(pagehit.php);
?>
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>My Home Page</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="language" content="en" >
<link href="./asset/44ab1983/css/style.css" rel="stylesheet">
<script src="./asset/16eb9947/jquery.js"></script>
<style>
html,
body
{
width: 100%;
height: 100%;
background-color: #e6e6ff;
}
#product-item
{
background-color: white;
padding-left: 10px;
padding-right: 10px;
}
</style>
<script type="text/javascript">
$(document).ready(function()
{
public function example(arg)
{
// function code
}
});
</script>
</head>
<body>
<div>
content of the div
</div>
<div>
<table>
<tr>
<td>
td content
</td>
</tr>
</table>
</div>
<div>
content of the div
<a href="#">link</a>
</div>
</body>
</html>
There you have it! An easy way to track your website's visitors!!!
Now that you've got your website with all the bells and whistles, you can migrate it to your live server to make your website live online for your visitors all over the world to see.
There are plenty of web hosting providers out there: both for paid hosting and for free hosting. Just Google the term "free web hosting" and it will give you a lot of results to choose from.
Here is one that I found on the Internet, the one that I use on one of my websites: https://webfreehosting.net/
As with all free web hostings, there are certain things you can and can't do, such as you can't incorporating your payment application to do ecommerce transactions. To be able to do ecommerce transactions, you'll have to subscribe to their paid hosting service that normally costs about $2.99 per month.
For the free web hosting plan, you are limited to certain bandwidth as well. Not only that, even if you have a paid hosting plan with them and if your website receives a lot of traffic, this hosting provider throttles your bandwidth to slow down your visitors visiting your website, making your website to load very slowly.
An example of that is my website ZeroNilZilch.COM, which receives very heavy traffic, and as a result, this hosting provider throttles my bandwidth, making it very slow to load.
You may have already noticed that the website is very slow to load. This is because my website receives very very heavy traffic and this hosting provider throttles my bandwidth traffic.
So please be patience with my website when surfing my website and please keep visiting my website regularly when you need to. I would love to have you all continue making use of the resources in my website on a regular basis.
Thanks!!!
If you compare ZeroNilZilch.COM with the rest of my websites, say, Noon2Noon.COM, or Rainbow180.COM, or PostalJobHotline.COM, ZeroNilZilch.COM takes a long time to load while the others are very fast to load. This is due to this hosting provider throttles my loading speed because of ZeroNilZilch.COM generating very very heavy traffic.
As you can see, even when I follow their policy very religiously and not even anywhere close to breaking their policy, they still impose limits on my website, something that I'm not very happy about. So this is the only one factor that I'm not happy about this hosting provider.
So please read their policy. Also, you need to abide by their policy on all other aspects of the "free plan" to avoid being shut down. So make sure you read their policy on what you can do and on what you "CAN'T" do.
I hope you take this warning seriously because once you're shut down, you can't get another account with the same host provider. You'll have to find another hosting provider.
All hosting providers have policy that they enforce very strictly. So don't loose your hosting account with this hosting that I mentioned above, because it is one of the best hosting providers out there, albeit, they impose bandwidth limits when your website receives very heavy traffic.
I don't know if other shared hostings do this or not. Anyhow, please be mindful of this scenario.
So good luck and have fun with your website, albeit be mindful of the policies placed on your hosting plan.
Here is a secret that no one will tell you about this hosting provider mentioned above, but I will: You can actually signup for many hosting accounts with this hosting provider so that you can host as many (of your) websites as you want.
Yes, that is right; you can have your websites hosted by this hosting provider and it is perfectly legal and they won't ban you for hosting multiple websites on their platform. Yes, that is correct! You can host multiple websites on their platform! I repeat: You can host as many websites as you want on their plaform.
All you have to do is signup each account for each of your websites using a unique email address and it will let you signup for multiple accounts to host multiple websites.
My suggestion for you is to create multiple email accounts, say, with Gmail.COM or with any other email services and using those email addresses to signup hosting accounts with this hosting provider to host all of your websites.
Yahoo Mail is also one of the best emai service providers out there and it on par with Gmail service. I, myself, use both Gmail and Yahoo Mail for my emails needs. I singed up multiple email accounts with both and the best part is that you can signup for an ulimited email accounts.
Remember that one email address is only good for one hosting account to host one website. So if you have multiple websites (as I do), you need to have multiple email addresses so that you can use those email addresses to signup hosting accounts with this hosting provider.
One email address is only good for one website.
You can use (your) same name and same address and the same other information as well.
You don't have to use different name and different other information.
Email address is only one that needs to be unique for each account.
One Last Warning:
Please DO NOT abuse your free hosting priviledges. In other words, please read their 'Users Policies' carefully and obey their rules and guidelines.
Just because it is free and you can signup for multiple accounts, it doesn't mean that you can do anything you feel like doing.
So enjoy your multiple hosting accounts for your multiple websites, but be mindful of their rules and guidelines and DO NOT abuse your priviledges.
There you have it!
A secret that no one will tell you about it!!!
But I am telling you that!!!
So good luck and have fun with your websites, albeit be mindful of the policies placed on your hosting plans.
Once you'd signup an account with the above mentioned webhosting service provider, you can login to your account and the dashboard/webspace looks like the following:
On the left side is where it lists your account detail that looks like the following:
As you can see in the dashboard area or webspace area, you have several options to choose to go into more specific tasks. It shows all kinds of options for you to choose.
For example, when you click on an FTP Manager, it takes you to an FTP manager area where you can setup/create FTP accounts.
From there, you can fill out and supplying the various required FTP account information.
After creating an FTP account, now you're ready to upload your website files to your FTP account.
You will need these FTP account information to be used with your FileZilla application to transfer your files to and from your local computer to your FTP account.
See my other tutorial called Introduction to FileZilla.
Next, you need to create database(s) by clicking on the Database Manager and fill out the appropriate information. You will need these information to use with your database "PDO" connection.
See my other tutorial called Introduction to PDO.
At this point, you're done with creating FTP and Database accounts and presumably all your website files have been uploaded to your FTP account and your database tables and content have been created and setup and ready to go.
Next, you need to setup your domain. Somewhere in your dashboard area, there is a topic called Domain() Manager. Click on that topic to go to setup your domain and it opens up a domain creation view that looks like the following:
In the above area where you can setup/create your domain accounts by supplying the necessary information.
There are several options to choose from depending on your actual situation. You can actually buy your own domain from this hosting provider on the spot by clicking on 'register a domain. You can also transfer your domain to this hosting provider if you had registered it with some other domain registrars.
Either way, you're good to go with this hosting provider.
Personally, I recommend you to register your domain with other hosting/domain service providers that can offer you cheap domains. There are plenty of cheap domain service providers out there and one that I use personally is called https://www.namesilo.com/
If you're using domain from other domain service providers, just type the name of your domain in the box under: 'Host an existing Domain', for example: myfirstsite.com. And click on "Host Domain" button. Don't forget to put the "DOT" suffix name after your domain as shown in the example. This can be .com, .net. .org, etc.
If you're using a domain from other domain service providers, make sure that the domain is fully active, otherwise, this hosting is not able to detect your domain from the central server of the World Wide Web consortium who actually is maintaining the domains as a central location.
The domain service providers are just third parties sellers selling domains from the main body organization called the World Wide Web consortium.
After that, it should give you some sort of result at the bottom of your domain space if it is hosted successfully with this hosting provider.
In the result that you just created and hosted successfully, look at the heading at the far right side that says "Settings" and click on that topic. It should slides down to reveal more content. Now click on the topic: "DSN" (stands for 'Domain Name Server') and it should slides down further to reveal more content on that topic.
There are lots of options for you to choose, but for beginners, you only need to be concern with the topic called "NS".
Next, look under the heading called "Type" on the left side and scan down to find "NS" which stands for 'Name Server', or short for 'Domain Name Server'.
You need to copy this domain name server (address) so that you can use it to link your domain that you had registered with other domain service provider to your hosting account with this hosting service provider.
In a simplier way of saying is that, this domain name address is used to link your domain name that is residing in your third party domain registrar to this web hosting provider. Your third party domain registrar needs this information to link the two servers together.
Once you have the domain name server address, you need to go back to your domain service provider that you had registered and had an account with and login to that account so that you can supply this "NS" information to that domain provider.
In your (third party) domain service provider dashboard space, there should be an option that says "Domain Manager" and you need to navigate to that domain manager space and look for some sort of topic called "domain service name entry" or similar to that nature and then supply the "NS" information to it accordingly.
Hint: In your third party domain service registrar, look in the "Domain Manager" and click on one of the options listed on your particular domain. Maybe try clicking on the name of your domain and see what options it reveals.
Different domain service providers have slightly different look and feel, but all of them should have something in common, and that is, a box for you to enter the "NS".
Here is an example of domain entries:
Name Server 1: ns1.example.com
Name Server 2: ns2.example.com
Name Server 3: ns3.example.com
Name Server 4: ns4.example.com
Name Server 5: ns5.example.com
As you can see above, there are several domain name servers that you need to enter, but for most hosting providers like the free web hosting service provider that I mentioned above, you only need to supply only two "NS" entries are enough.
Once you've entered the "NS" information and submitted, it will take about 12 hours to take effect, although some domain providers take longer or shorter.
Meanwhile, after about an hour or so after you've submitted your "NS" information, you can try to load your website to see if it's effective or not. I've found that with most domain service providers, it only takes about one hour to take effect and not more. Try it after an hour of the entry and see if it is effective.
At this point, everything has been covered to enable you beginning website developers to able to create websites and host them in a live server. You can keep making improvements to your websites as they get more sophisticated.
There you have it! Have fun with your websites!
<?php class Foo{ public test($x) { if ($x == 1){ // do something with $x }elseif ($x == 2){ // do something with $x again }elseif ($x == 3){ // do something with $x again }else{ // do nothing with $x } } private getFoo(){ for ($i = 1; $i < 10; ++i){ // do something with $i } } } ?>
<?php class Foo { private $arr; public function config() { return [ 'id' => 'app', 'basePath' => dirname(__DIR__), 'component' => [ 'request' => [ 'csrf' => 'csrf-app', ], 'user' => [ 'identity' => 'app\model\User', 'autoLogin' => true, 'cookie' => [ 'name' => 'id-app', 'httpOnly' => true ], 'error' => [ 'action' => 'site/error', ], ], ], ]; } // end config() public function example($arg1 = null, $arg2 = null) { if (!empty($arg1)) { // do something with $arg1 foreach ($arg1 as $item) { // do something with $item try { switch ($item) { case 1: // do something if ($something) { for ($i = 0; $i < $something; $i++) { $dosomething[$i] = getSomething(); } } elseif ($otherThing) { foreach ($otherThing) { try { $doOtherThing = getOtherthing(); } catch (Exception $e) { // doOtherThing with $e; } catch (OtherException $o) { // doOtherThing with $o } } // end foreach } // end elseif ($something) break; case 2: // do something break; case 3: // do something break; default: // do something break; } // end switch } // end try catch (Exception $e) { // Error! Do something with the error $e } } // end foreach } // end if $arg1 is not empty elseif ($arg2 != null) { // do ... while and for() loops $test = false; do { for ($i = 0; $i < count($arg2); ++$i) { if ($arg2[$i] == 1) { $test = true; break; } } // end for() } // end do while ($test == false); } // end elseif else { // do nothing return ''; } $connect = ''; $attempt = 3; while (!$connect AND $attempt > 0) { $authConn->connect(); $connect = $authConn->isConnect(); $attempt = $attempt - 1; } } // end example() } // end class Foo ?>
<?php class Foo { public addValue($x, $y) { // method body } // end addValue() private getFoo() { // method body } // end getFoo() } // end class Foo ?> Notice the comments: // end addValue(), // end getFoo(), // end class Foo
<?php class Foo { if ($expr1) { // lengthy multiple statements code block // lengthy multiple statements code block // lengthy multiple statements code block } // end if ($expr1) elseif ($expr2) { // lengthy multiple statements code block // lengthy multiple statements code block // lengthy multiple statements code block } // end elseif ($expr2) else { // lengthy multiple statements code block // lengthy multiple statements code block // lengthy multiple statements code block } // end else if ($expr2) try { // lengthy multiple statements code block // lengthy multiple statements code block // lengthy multiple statements code block // lengthy multiple statements code block } // end try block catch (Exception $e) { // lengthy multiple statements code block } // end Exception $e catch (OtherException $o) { // lengthy multiple statements code block } // end OtherException $o } // end class Foo ?> Notice the comments: // end if ($expr1), // end elseif ($expr2), // end else if ($expr2) // end try block, // end Exception $e, // end OtherException $o // end class Foo
[...elements...]
is used instead of the regular long form array(...elements...).
And (shorthand) arrays used in the configurations can optionally contain a comma (",") as well at the end of the array element list. As examples, the below configurations contain a comma following the last array element [particularly 'charset => utf8' for shorthand array] even though there isn't another array element following it.
As a matter of fact, both regular arrays and shorthand arrays can contain a comma (",") at the end of the array element list. This is legal (for both) and you can choose to put it there or take it out and it is perfectly fine. It's not a requirement to have a comma at the end of the last array element. So it's up to your personal preference.
However, this coding standard strongly recommends putting a comma after all array elements because it avoids bugs. The reason that it is legal to have a comma after the last array element is to speed up coding process and avoid bugs. So it is strongly suggested that you put a comma after the last array element to avoid bugs.
Here is a snippet of code using the regular array:
$requirement = array(
array(
'name' => 'PHP Some Extension',
'mandatory' => true,
'condition' => extension_loaded('some_extension'),
'by' => 'Some application feature',
// notice the comma after this last array element!
'memo' => 'PHP extension "some_extension" required',
), // <== notice the comma! this is perfectly legal!
);
In the following, a configuration is used to create and initialize a database connection. Notice the comma following the array element 'charset => utf8' even though there isn't another array element following it:
$config = [
'class' => 'core\db\Connection',
'dsn' => 'mysql:host=127.0.0.1;dbname=demo',
'username' => 'root',
'password' => '',
'charset' => 'utf8', // <== notice the the comma! it's perfectly legal!
];
$db = core::createObject($config);
If you look at the example preview earlier [in the function config()], you'll see shorthand arrays are being used and all last elements of the arrays have a comma after each of the last element of the arrays. So it is definitely recommended that shorthand arrays and a comma on the last element of the array are being used -- on your own programming chores -- because it is much cleaner and easier to visualize, and most importantly, it speeds up your application development by eliminating bugs and unnecessary syntax corrections.
$a = $b + $c; // add b to c Do not do this: $a=$b+$c; //add b to c if ($b == $c) Do not do this: if($b==$c) Do not do this: for($i=0;$i<10;$i++) Do this instead: for ($i = 0; $i < 10; $i++)
class Example { }That looks very good, but on longer reserved/keywords like public, private, protected, static, etc., it looks awful. For examples:
public class Example { } private class Example { } protected class Example { } static class Example { } Or for conditional structures: if (condition) { } else { } elseif { } foreach { }As you can see, indenting four spaces for all code structures, [although very uniformed], is a bad idea, and it looks weird visually and logically. That's why I chose to indent the code according to the length of the reserved keyword.
class Example { private $myVar; public myMethod($x) { // ... code return $x; } // ... more class code here! }Nowaday, the trend is leaving the legacy style behind and more and more programmers are adopting new modern style of coding and my coding convention is a byproduct of the new trend. So do these instead:
<?php class Foo { /** * class body declaration. * notice the four spaces indentation of the class' opening "{" and * the five spaces indentation of the method declaration: public. * notice also that the opening/closing parentheses are aligned vertically at the * same level, and all respective code body are inside the parentheses. * it looks very clean and easy to follow the logic of the code flow. */ public $arr = array(); private $dbConnection; public addValue($x, $y) { // method body // notice that the indentation and placement of the opening "{" and // closing "}" directly leveled with the last letter of its keyword. } private getFoo() { // method body // notice that the indentation and placement of the opening "{" and // closing "}" directly leveled with the last letter of its keyword. } protected getBar() { // method body // notice that the indentation and placement of the opening "{" and // closing "}" directly leveled with the last letter of its keyword. } // this is ok, too, and is preferred, indent five spaces to align with // 'public' which is the most commonly use visibility clause protected setFoo($x) { // method body } public addFoo() { // method body } // this is ok abstract protected function zeroBar(); { // method body } // this is ok, too, indent five spaces to align with 'public' which is // the most commonly use visibility clause abstract arrayHelper() { // code body here for this abstract method } public static function bar() { // method body } // this is ok, too private static function bar() { // method body } // this is ok, too, indent five spaces private static function bar() { // method body } final public static function bar() { // method body } // same as above final private static function bar() { // method body } static function bar() { // method body } // this is ok, too function bar() { // method body } // this is ok, too, indent five spaces to align with 'public' function bar() { // method body } // this is ok, too, because it has at least five spaces indented for body code function bar() { // code body. // notice the placing of "{}" at the same level as the method declaration. // notice also the indented five spaces for coding statements // starting position // ..... } } // end class body ?>
trait ArrayHelper { // main body code of a trait }CSS: For CSS and other languages (such as Javascript, Java, C#, C/C++, etc.) do follow the guideline outlined in this coding standard and follow a five-space rule to align with 'public' visibility clause. For examples:
<style> html, body { width: 100%; height: 100%; background-color: #e6e6ff; } #product-item { background-color: white; padding-left: 10px; padding-right: 10px; } div .some-selector { background-color: white; width: 400px; height: 200px; } .nav li > form > button.logout { padding: 15px; border: none; } a.asc:after, a.desc:after { position: relative; top: 1px; display: inline-block; font-family: 'Glyphicons Halflings'; font-style: normal; font-weight: normal; line-height: 1; padding-left: 5px; } a.asc:after { content: "\e151"; } a.desc:after { content: "\e152"; } </style> <script type="text/javascript"> $(document).ready(function() { public function example(arg) { // function code } // this is ok, too function example(arg) { // function code } // this ok, too, to align with 'public' function example(arg) { // function code } // this ok, too static public function example(arg) { // function code } }); </script>
<!DOCTYPE html> <html lang="en-US"> <head> <title>Untitled</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="language" content="en" > <link href="./asset/44ab1983/css/style.css" rel="stylesheet"> <script src="./asset/16eb9947/jquery.js"></script> <style> html, body { width: 100%; height: 100%; background-color: #e6e6ff; } #product-item { background-color: white; padding-left: 10px; padding-right: 10px; } </style> <script type="text/javascript"> $(document).ready(function() { public function example(arg) { // function code } }); </script> </head> <body> <div> content of the div </div> <div> <table> <tr> <td> td content </td> </tr> </table> </div> <div> content of the div <a href="#">link</a> </div> </body> </html>
<?php if ($expr1) { // single statement block. notice the use of braces even though it is not required! } elseif ($expr2) { // elseif code block. single statement block } elseif ($expr3) { // multiple statements code block // multiple statements code block // multiple statements code block } else { // else single statement block code block }
<?php switch ($expr) { case 0: echo 'First case, with a break'; break; case 1: echo 'Second case, which falls through'; // no break case 2: case 3: case 4: echo 'Third case, return instead of break'; return; default: echo 'Default case'; break; }
<?php while ($expr) { // structure of code block }
<?php do { // structure of code block; } while ($expr);
<?php do { // structure of code block; } while ($expr);
<?php for ($i = 0; $i < 10; $i++) { // for code block }
<?php foreach ($iterable as $key => $value) { // foreach code block }
<?php try { // try code block } catch (FirstExceptionType $e) { // catch code block } catch (OtherExceptionType $e) { // catch code block }
<?php $closureWithArg = function($arg1, $arg2) { // body };
<?php $longArg_noVar = function( $longArgument, $longerArgument, $muchLongerArgument ) { // code body }; $noArg_longVar = function() use( /* notice naming variables using enumerated variables, */ /* although $longVar1 is fine */ $longVar1, /* notice naming variables using enumerated variables, */ /* although $longVar2 is fine */ $longerVar2, /* notice naming variables using enumerated variables, */ /* although $longVar3 is fine */ $muchLongerVar3 ) { // code body }; $longArg_longVar = function( $longArgument, $longerArgument, $muchLongerArgument ) use( // readability: indents some spaces $longVar1, $longerVar2, $muchLongerVar3 ) { // code body }; // this is ok too $longArg_shortVar = function( $longArgument, $longerArgument, $muchLongerArgument ) use($var1) { // code body }; // this is ok, too $shortArg_longVar = function($arg) use( $longVar1, $longerVar2, $muchLongerVar3 ) { // code body };
<?php $foo->bar( $arg1, function($arg2) use($var1) { // code body }, $arg3 );
<?php // PHP 5.3 and later: namespace Vendor\Model; class Foo { // code block }
<?php // PHP 5.2.x and earlier: class Vendor_Model_Foo { // code block }
<?php namespace Vendor\Model; class Foo { const VERSION = '1.0'; const DATE_APPROVED = '2012-06-01'; }
<?php namespace Vendor\Package; use FooInterface; use BarClass as Bar; use OtherVendor\OtherPackage\BazClass; class Foo extends Bar implements FooInterface { public function sampleFunction($a, $b = null) { if ($a === $b) { bar(); } elseif ($a > $b) { $foo->bar($arg1); } else { BazClass::bar($arg2, $arg3); } } final public static function bar() { // method body } }
Both class and object have the same meaning and both achieve the same purpose but differ only in the way they're implemented and used.
A class consists of constant variables, properties, and methods. Those are the three basic attributes of a class. That's all a class is: it has three attributes -- a very simple concept and yet very powerful.
Consider the following class definition:
<?php
class MyClass
{
// 1st attribute of the class (MyClass):
// declaring class constant variables
// COMMAND_EVENT_START, COMMAND_BEFORE_START,
// COMMAND_AFTER_START are constant variables
// command_start, before_start, after_start are constant values
const COMMAND_BEFORE_START = 'before_start';
const COMMAND_EVENT_START = 'command_start';
const COMMAND_AFTER_START = 'after_start';
// 2nd attribute of the class (MyClass):
class properties: properties must be declared prefacing with visibility control
public, protected, private are visibility control:
public $make = 'Toyota';
protected $model = 'Tundra';
private $color = 'grey';
// 3rd attribute of the class (MyClass):
class methods: methods must be declared prefacing with visibility control
public, protected, private are visibility control:
public function test1()
{
// will output: An object is just a copy of the class.
echo "An object is just a copy of the class." . "\n";
}
public function test2($str)
{
// will output whatever string got passed in via $str
echo $str . "\n";
}
}
?>
And then consider this object creation:
$str = 'An object is just a copy of the class.';
creating an instance of MyClass()
$obj is an instance of the class MyClass. it is a copy or a clone of MyClass.
$obj = new MyClass();
$obj->test1($str);
will output an error message saying argument $str is undefined in test1().
$obj->test1();
will output ----> An object is just a copy of the class.
$obj->test2();
will output an error message saying test2() requires at least one argument.
$obj->test2($str);
will output -----> An object is just a copy of the class.
A class
is the program you write (i.e., the MyClass
class implementation above); while object
(i.e., $obj) is the copy of the class or the clone of the class, most often being known as the instance
of the class.
A class
resides in ROM
(permanent memory area) whereas object
(i.e., $obj) resides in RAM
(temporary memory area.)
In ROM
, data is stored there permanently even when the computer is turned off. In a RAM
memory area, on the other hand, data get stored temporarily while the program is running or while the computer is still turned on. When the computer is turned off, the RAM
data (i.e., $obj) is completely erased and is no longer stored in the RAM
.
Instances
of a class can be useful only while the program is running or while the computer is turned on; and when the program is not running or when the computer is turned off, instances
of a class are no longer useful to a program; and therefore, it is stored in a temporary memory area.
Instances
of a class can be created 'on the fly
' at any time when needed by a program [as you can see above: $obj = new MyClass()].
Instances
of a class are often being created from everywhere when needed (i.e., libraries, frameworks, and other classes, etc.)
So there is no need to store instances
of a class permanently in permanent memory spaces and wasting valuable memory spaces.
It is typically being used by website owners who need to upload their website files from their local computer to a remote server that their website is hosting on. You can also use FileZilla to download files from a remote server that your website is hosting on as well.
So it is a file transfer application using an FTP file transferring protocol. So FTP is an acronym for File Transfer Protocol.
As always, lots of tutorials on this subject are available on the Internet, particularly on YouTube and elsewhere in HTML. So instead of actually doing a tutorial that can be found easily on the Internet, I'm going to just refer you to those tutorials and let you follow those tutorials instead. Why is there a need for me to do a tutorial that is readily available on the Internet? The answer is that absolutely no!
So here we go:
Here are brief summaries of steps on how to configure FileZilla client after you'd watched tutorials listed above and as well as having FileZilla downloaded and installed onto your computer.
Download the FileZilla onto your computer.
Once you've downloaded it, extract it using zip extracting applications like WinZip Express Zip WinRAR or WinRAR here! PeaZip
Collecting FTP Details
After you installed FileZilla onto your local computer, you now are ready for the transferring process. But first thing first, you need to gather the FTP details of your hosting account. Each hosting provider is different in how they layout their FTP information. For Hostinger users, the information is located in the hPanel's menu, under:
Files -> FTP Accounts
Most hosting providers have a dashboard area or webspace area where you can see options to choose to go into more specific tasks. For example, for my hosting provider, it has a dashboard that shows all kinds of options for me to choose. For example:
Here, when I click on an FTP Manager, it takes me to an FTP manager area where I can setup/create FTP accounts. In the FTP manager I can create an account by creating a username and a password. I will need these information that I created to be used in the FileZilla. Here is what the inforamtion in the FTP manager looks like:
Once you have an FTP information, you can use it to configure FileZilla. Now all you have to do is click on your FileZilla icon to open it and you'll see a screen that looks like the following:
As you can see in the diagram above, on the left side is for a local working area or section. This is where you can configure your connection information and selecting files or directories to upload to a destination on the right side. On the right side is a remote site or destination area to upload to.
In the above diagram, you can provide information to do a "quick connect" connection. However, I strongly suggest that you don't use a quick connect but instead go through a longer connect, which I will detail it for you. It will save you time later on. A quick connect doesn't remember your connection setting after your computer is turned off, while a longer connection will.
Here is for the longer and more efficient connection:
Click on "File" at the top left corner of the diagram shown above. The drop-down menu will reveal several options but you want to choose "Site Manager" option. A site manager screen should open up and should looks like the following:
Pay close attention to a section called "Select Entry" where all of your FTP accounts are to be created. In my case, I have four FTP accounts: one account to connect to a Monday-Sunday website FTP hosting account; another to connect to a Noon2Noon.NET FTP hosting account; another to a Postal FTP hosting account; and finally to a ZeroNilZilch FTP hosting account.
So in my case, I have four different hosting service providers; and therefore, I need to have four different entry names (Monday-Sunday, Noon2Noon.NET, Postal, ZeroNilZilch), each connecting to its individual FTP account.
So in your case, the "Select Entry" section and "My Sites" area should be empty because you haven't create a "New Site" yet.
To create a "New Site" entry name similar to the four shown in my case, click on another option called "New Site" down below at the bottom of the diagram. Once you click on "New Site" option, an entry inside the "Select Entry" under "My Sites" area will appear for you to enter an entry name similar to the four entry names that I've created.
Name your entry name any name you like. It's just a name to differentiate from one entry name to another.
Once you created an entry name, you need to configure FileZilla to connect to your FTP hosting account by hi-lighting an entry name similar to what is shown with ZeroNilZilch right now. As you can see, once you hi-light it, the entire diagram flickers and changes the configruation and reveals input boxes for you to enter an FTP information.
For example, for me, I hi-lighted or selected 'ZeroNilZilch' in the "Select Entry" section, and then to the right, I entered 'zeronilzilch.com' in the host box.
This information is obtained from my FTP hosting account created earlier. In your case, you can get this information and the rest of the FTP information from your FTP hosting account.
For port, I use 21, which is a common port for a shared hosting. All you need to know about port is that if you rent or use a free web hosting from any vendor, use port 21, because most likely they're shared hosting. All shared hostings use port 21.
For protocol, select FTP; for encryption select FTP over TLS (just like what it looks like on the screen); for logon type, use 'Normal'; for user (or username) enter the actual FTP username you got from your hosting vendor; likewise, for the FTP password.
That is it! Nothing else to enter. Very easy! Now all you have to do is click on the button "Connect" to connect to your FTP hosting server to begin the transfer process.
After you click on "Connect" it should looks similar to the partial diagram shown below. I show only partial diagram to avoid revealing my other information to the public. But this partial diagram should give you a good idea of how it works.
As you can see, it is very easy to use FileZilla.
Now since you've created your connection the longer and more efficient way, next time you need to connect to your FTP account, just open up your FileZilla application that should looks like the default view similar to the one that has a "quick connect" option on it (shown earlier).
Yes, that is the default view of FileZilla (shown earlier) allowing you to either do a "quick connect" or do a longer more efficient connect.
So since you went through a series of steps to do a longer and more efficient connect already, now all you have to do is click on one of two things:
First the hard way:
You can click on "File" at the top left corner of the diagram shown above. The drop-down menu will reveal several options but you want to choose "Site Manager" option.
A site manager screen should open up and should looks like the "Site Manager" diagram shown earlier. From there, all you have to do is hi-light an entry name to make it looks like the one shown on "ZeroNilZilch." This will activate your FTP account setting and ready to be connected to. Next, just click on the "Connect" button and it will try to connect to your FTP hosting account.
Well, that was somewhat the hard way. Sort of!
Now the easy way:
The same thing: you can click on "down arrow" or a drop-down menu just below "File" at the top left corner of the diagram shown above. The drop-down menu will reveal an entry name (or several entry names if you have more than one as in my case).
Now all you have to do is click on an entry name in the drop-down menu and a "Site Manager" showing your entry name is shown ready to be connected to your FTP hosting account. Next, just click on "Connect" button and it will try to connect to your FTP hosting account.
Once connected it should looks something like a partial diagram shown below.
Since it is a partial listing of the actual full view, you're not able to see all options you can do with the connection. You'll have to make use your FileZilla on your own from here on. It is very easy because all the hard part has been explained and now is just the easy part.
Well actually, you can see a somewhat full view of the default view shown earlier and you should get a good idea of how you can select a particular file or directory to upload to.
But briefly, as you can see from the above diagram, there are two parts: one on the left side contains your local file directories where you can select and upload them to the destination on the right side. Simple enough?
On the left, because of a partial listing, I am not able to show you that you can actually select or pull down a drop-down menu to select any directory from your local computer to upload to the destination on the right side. Yes, you can select or pull down a drop-dwon menu on the left side and select any directories or files to upload to the destination on the right side.
Likewise, on the right side, you can select (or pull down a menu--well, mainly select) a directory to receive the content being uploaded to it. In other words, to upload a file or files or directory or directories, you need to know where in directory destination you want to upload the content from the left side to on the right side. Self-explanatory!
Once you've selected the destination directory on the right, and then you can go ahead and upload the content on the left side by hi-lighting or selecting it and right-click it to reveal several options. One of the options is "upload" and select "upload" to upload it. Self-explanatory!
Likewise, on the right, you select a particular file or files or directory or directories by hi-lighting it and then right-click it to reveal several options. One of the options is "download" and click on it to download. Self-explanatory!
That is it! Have fun using FileZilla.
For a very good introductory tutorial on the Web, please check out the following tutorials:
The MVC Pattern: PHP, MVC and Best Practices The MVC Pattern and PHP, Part 1 The MVC Pattern and PHP, Part 2 The MVC Pattern: An Introduction to the Front Controller Pattern, Part 1 The MVC Pattern: An Introduction to the Front Controller Pattern, Part 2For a more advanced pattern methodology, please check out MVVM (Model-View-ViewModel). MVVM was invented by Microsoft for desktop programming in 2005 using event driven programming techniques.
MVVM was invented by Microsoft architects Ken Cooper and Ted Peters specifically to simplify event-driven programming of user interfaces, i.e., GUI applications. The pattern was incorporated into Windows Presentation Foundation (WPF) (Microsoft's .NET graphics system) and Silverlight (WPF's Internet application derivative).
MVVM is more suiteable for desktop programming than Web programming.
So if you're programming for the Web use MVC and if you're programming for the desktop use MVVM.
Advanced Pattern: The advantages of MVVM over MVC Advanced Pattern MVVM For Desktop: Model-View-ViewModel Design PatternFor a more advanced pattern methodology using MVC, please check out on the 'how to build your own framework':
Advanced Pattern in MVC: Code Your Own PHP MVC Framework Advanced Pattern MVC and PHP: A Beginner's Guide To MVC For The Web ProgrammingAn MVC is an acronym for Model View Controller.
It is a methodology to uniform the way people program applications. Remember that in programming, programmers tend to have their own unique way of doing things and that causes a lot of confusions, especially in a team work where programmers are working in the same project. There is no way of knowing what each programmer is trying to do in the same project. There is a compatibility issue.
There is no uniform pattern way of doing things; each programmer is doing things each his/her own way of doing things; for example, in a team work in the same organization working on the same project, one programmer puts data handling with the organization of that data while another programmer puts the same data handling with the displaying of that data to users; and the two programmers are completely oblivious to what the other programmer is trying to do.
This causes the finished product to be in-efficient, in-compatible, and not robust and not to mention the cost of having programmers to do other similar projects that take a long time to complete because of the codes are not re-usable.
So to be efficient, robust, scalable, upgradable, re-usable, and easy to maintain, it has to be a unique way of doing things for all programmers to understand and work in a uniform way so that all programmers can know systematically what the other programmers are doing in the same project, even if each programmer is located far away from each other and haven't seen each other's actual work.
To solve this issue, the MVC was developed.
To understand the concept of MVC, think of it in term of an organization mentioned above where there is a manager, some programmers, and the customers who want to get the application done.
The customer is the view presenting to the manager of what to be done, telling the manager the criterio of what need to be done. For example, the customer may wants the website that has ecommerce and social media applications capability installed in it.
The manager is the controller, handling the organization (or criterio) of the task dictating and given by the customer.
The programmers are the model handling of data or instructions given by the manager and using those instructions from the manager to proceed to do all of the programming work.
Notice that the manager, or the controller, does not know how programmers perform their tasks for the project: he/she doesn't care how their programmers do their jobs as long as their programmers perform the task that meets the criterio given to them.
Likewise, the programmers know nothing about who the customer is and what he/she looks like or wants. The programmers don't really care who the customers are; all they care about is getting the task done.
Likewise, the customer knows nothing about who the programmers are and what they look like or where they're at or from. The customer only cares about is getting the website completed in the agreed timeframe.
And also, the programmers don't know how the manager got the instructions or whom he'd or she'd got it from. The programmers don't know what the heck the manager is doing either: the programmers just don't care what the manager is doing or how he/she is doing. It's not their job to know what the manager is doing.
Keep this seperation of concern in mind when you're dealing with MVC pattern.
As you can see, the three parties are completely independence of one another: in other words, they don't need to know what the other is doing or how the other is doing things. They all can do things in their own seperate unique ways without intertwine with one another.
Now imagine you're a large or small organization where you have lots of programmers working on all kinds of applications large or small and those programmers are spreading all over the world.
If all these programmers know MVC pattern, they can work on the same projects in different part of the world without knowing what the other programmers are doing on the same projects that they're working on.
This is the beauty of an MVC pattern where one group of developers working on the same project as the other group is located in far away from each other and they still can accomplish the same project without knowing what the other groups are doing.
In an MVC pattern, each party is seperate from one another and each party knows nothing about what the other party is doing. In an MVC pattern, each party doesn't need to know what the other party is doing as long as each party is doing its job in a unique/uniform way using MVC pattern.
Let's review: the customer requests to the manager telling the manager of what kind of application needs to be done; the manager, in turn, tells the programmers what tasks need to be done. That is all! Nothing else!
The customer doesn't know what the manager or the programmers are doing as long as the application gets done; while at the same time, the manager doesn't need to know what the programmers are doing as long as the task of getting the application done; and likewise, the programmers don't need to know what the customer looks like and how that customer's exact words to the manager--it doesn't matter.
When you approach to building an application in an MVC pattern, think of the above analogy -- it will help you a lot.
Here is a brief example on how to program in an MVC pattern.
In an abstract way, usually the index.php front page or a catalog page or an HTML form is the view 'V' rendering the page to the customers/users to allow customer/users to navigate throught the page looking to do/order things.
In the index.php front page or a catalog page or form, there should be some buttons or links for customers/users to navigate to the products or area of interest.
That's all the view 'V' is; nothing special: just HTML pages or forms that contain contents and buttons or links. Nothing else!
Now when a customer/user clicks on the button or link, it redirects the customer/user to another part of the website or sometimes to another remote site.
Now before it reaches another part of the website or another website remotely, it has to go through a controller 'C' (or a middle man or a manager in our case). It has to hand over the instructions to the manager to decide on what to do next. Logically, a manager will hand over the instructions to programmers to start performing the tasks.
Remember that the programmers are the model M who do all the heavy work.
In the case of a button or link, it contains a url to redirect to:
'http://www.example.com/index.php?site/controller'
Before I show you how to parse this url (above), I want to show you the server access command using .htaccess file. Put this file in the same directory as your index.php in the root directory of your project. This index.php file is typically called a starting script file.
This is the hand over the instructions to the programmers using routes.
Open up your text editor and create a file called .htaccess and put the following content inside it.
File: .htaccess
# please remove all these textual comments because it may problems!
# the .htaccess file starts with this line
RewriteEngine on
# the above line says turn on the server
RewriteBase /
# the above line says look for content after http://www.example.com/
# with '/' being the last '/' after '.com'
# next two lines say if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
# with !-d for a directory and !-f for file
# otherwise forward it to index.php (using the rule shown below)
# in other words, if none of the two conditions above is met or true,
# go to execute index.php, with index.php being the starting script file, i.e.:
# http://www.example.com/index.php
RewriteRule ^(.*)$ index.php?url=$1 [L,QSA]
# continuing on above line: after the 'index.php?' is the querystring
# this is like: ?controller/action/param1/param2/para3/para4/para5/...
# so this string: url=$1 [L,QSA] is just for the server to read!
# the "L" stands for link, the Q for query, S for string, A for append
# the string "url" is the name of the querystring that you will need to
# refer to when you parse your route. see function splitUrl() later on!
# the below two lines are just more rules and server options
# the first allow json file to go through and the second for options
RewriteRule \.(json)$ - [F]
Options -Indexes
# you don't need to understand any of this content in this file
# just use it "AS IS" but don't forget to remove my textual description!
# one important note: don't forget to remove the RewriteBase / entirely
# if for some reason your website doesn't load!
# I found that for some shared hosting it causes a problem!
# so if it doesn't load, just remove the RewriteBase / entirely
# for more on this topic, please Google the Web and there are
# plenty of tutorials on the Internet on the topic of .htaccess file!
What the above .htaccess file does is allowing you to do like this on your url route:
<a href="http://www.example.com/site/controller/param1/param2/param3/...">link</a>
or just:
<a href="site/controller/param1/param2/param3/...">link</a>
For img:
<img src="image/picture_1.jpg">
Notice that for img tag, there is no route needed. The img tags are typically being used in the view to display images; and therefore, routes are not needed. So you simply specify the src attribute that points to the directory of the image as you normally do in a non-MVC way.
For forms:
<form method="GET" action="http://www.example.com/site/controller/param1/param2/param3/..."></form>
Or just:
<form method="GET" action="site/controller/param1/param2/param3/..."></form>
For buttons:
<button type="button" onclick="http://www.example.com/site/controller/param1/param2/param3/..."></button>
Or just:
<button type="button" onclick="site/controller/param1/param2/param3/..."></button>
Basically, instead of having to write a complete route of
<a href="http://www.example.com/site/controller/param1/param2/param3/...">link</a>
on every link that you need, all you have to do is write just the querystring:
<a href="site/controller/param1/param2/param3/...">link</a>.
That's what the .htaccess file is for: allowing you to do a shortcut!
You will often route your form like this:
<form action="http://www.example.com/user/signup/param1/param2/param3/..." method="GET">
Or in a shortcut like this:
<form action="user/signup/param1/param2/param3/..." method="GET">
to route your user to the signup page. Notice that this is for a "GET" method. For a "POST" method see below.
The user part is the controller 'C' and the signup is the action. The rest are just "GET" method querystring.
If it is user/signup/id/guest/vip/ then user (the first part is always the controller 'C' and the second part signup is always the action, and the rest are extra GET parameters or querystring to send to the route.
In this case, there are three extra parameters that are being sent to the route: id, guest, and vip.
Please check out tutorials on the Internet to learn all these terms. Please check the following tutorial for more:
The MVC Pattern and PHPThe two most important terms are controller and action. Make sure you know what these two are and how to use them.
Hint: the controller is the class and the action is the method of the controller class. For example: user/signup.
<?php
// this is the controller
class User
{
// this is the action
public function signup()
{
// method code
}
}
?>
Note that you can use "POST" method as well and it will route your route via a "POST" and not via a "GET". For example:
<?php
<form action="user/signup" method="post">
<input type="hidden" name="id" value="My_id_123">
<input type="hidden" name="guest" value="This is the guest content">
<input type="hidden" name="vip" value="This is the vip content">
<input type="submit" value="Submit">
</form>
?>
The above form sends the POST variables to the route: user/signup. The .htaccess file routes this request through a normal HTTP REQUEST channel using a POST method.
DO NOT add the querystring in the POST method like you do with a GET method. This is illegal: user/signup/id/guest/vip/.
Remember that you handle a POST request the usual way where you send it to; for example, in the above case, it sends to the controller or class 'User' to execute the method signup(). Somewhere in the class 'User', particularly in the method signup(), is where you handle the request by doing this: $_POST['id'], $_POST['guest'], $_POST['vip'].
The keyword here is 'somewhere' because as you know the HTTP REQUEST once it is sent, it is available everywhere. So for class 'User', it is available everywhere inside it. Self-explanatory!
Now we need to parse the route or querystring.
This is also part of the handover of the instructions to programmers.
<?php
class route
{
public $base = array();
// now your main controller class will need to call
// this method init()
// you can do it inside your index.php starting file or from
// inside your main application file, for example:
// $route = new route();
// $route->init();
// for an example of a starting script file, see my other tutorial
// called "how to autoload classes using SPL" and there is an
// index.php file example shown at the very end of that tutorial!
// see a lengthy explanation of the difference between an
// index.php starting script file and the index.php/index.html
// front page view [below]!
public function init()
{
// class Base is the base controller class
// I haven't written it yet! Maybe I won't!
// did I mentioned that this is a very brief tutorial?
// this will not be a complete tutorial! just to give you
// an idea to move forward!
// check out the Internet on topic of "MVC" base controller class!
// basically, the "controller base class" is the main application
// class that handles all the logic of the entire application.
// see an example in my other tutorial called
// "how to autoload classes using SPL"
$this->base = new Base();
//get the url fragments from the url
$this->splitUrl();
// you need to require/include the appropriate file directory
require_once 'resource/dispatch/dispatcher.php';
$dispatch = new dispatcher();
// basically test to see if the url fragment in $x1 exists!
// suppose that a visitor of your website types in the
// url bar: example.com and the browser will try to
// to load: http://www.example.com/index.php
// now when it gets to splitUrl() it will return:
// $x1 is null, $x2 is null, $x3 is null, etc.
if (!isset($this->base->x1))
{
// so it comes here because $x1 is null!
// it will load the default file index page!
// don't be confused the default index page file with
// the starting index.php file!
// the two are completely different from one another!
// the default index.php/index.html page is your index
// front page typically can be found in the view, while
// the starting script file index.php is the file to
// jumpstart the application!
// for an example of the default index.php/index.html
// front page, see class dispatcher->init()
// where the code that looks like this:
// $this->base->render('index');
// as you can see, the statement above renders the view's
// index file: index.php/index.html in the 'view' folder!
// that's what the statement below is doing!
$dispatch->init();
// for an example of the script's index.php starting file,
// see my other tutorial called "how to autoload classes using SPL"
// and at the very end of that tutorial,
// there is a script file called index.php
// this script index.php starting file should be at the root
// of your application!
// if you look in my other tutorial called 'getting started
// programming for beginners', there is a section called
// 'How to Install WAMP on Windows', particulary, step 10.
// At the very end of that section where I show a
// localhost containing a sample application folder called
// "MyFirstWebsite"
// inside that folder there are only three items: 'css' folder,
// 'image' folder and the main starting script file 'index.php'
}
elseif (method_exists('dispatcher', $this->base->x1))
{
// now here, $x1 is NOT null!
// this is the case where you can do in the view like this:
// <a href="about">About</a>
// <a href="affiliate">Afilliate</a>
// <a href="signup">Signup</a>
// <a href="login">Login</a>
// this will load the controller page:
// dispatcher->about(), dispatcher->affiliate(),
// dispatcher->signup(), dispatcher->login()
// now what happens if you put an index "home" link/route in
// the view like the following?
// <a href="index">Home</a>
// here, x1 = 'index' but there is no method called 'index'
// in the 'dispatcher' class!
// so it won't come here and it will fall into the default
// condition below and displays the 'index' home page!
// now what happens if you put a link/route in the view
// like the following?
// <a href="user/signup">Signup</a>
// <form action="user/signup"></form>
// <a href="user/signup/id/guest/vip">Signup</a>
// <form action="user/signup/id/guest/vip"></form>
// obviously, x1, x2, and x3, etc, are not null!
// and therefore, it will still come here as well with:
// $x1 = 'user'
// $x2 = 'signup'
// $x3 = 'id'
// $x4 = 'guest'
// $x5 = 'vip'
// in this case, only x1 and x2 are relevant and both will be
// dispatched to the appropriate controller.
// see class dispatcher->user() later on!
$method = $this->base->x1;
$dispatch->$method();
}
else
{
// this is the default condition!
// if none of the conditions above are met,
// it will load the default index.php page!
// now what happens if you put a link/route in the view
// like the following?
// <a href="index">Home<></a>
// <a href="unknown">Unkown Link</a>
// <a href="noroute">Not Sure</a>
// all will come here because x1 = index, unknown, or noroute
// and x2 is null!
// so none of the conditions above are met,
// so all three cases above will come here and
// load the default index.php page!
// note that for your "Home" link, you can use the domain name
// as well (your domain), for example:
// <a href="http://www.example.com">Home</a>
// I recommend that you use the domain name for your "Home" link
// to avoid problems!
// if you use index or other unknown/undefined method of the
// controller (as shown above), it might give you an error saying:
// "Can't load the page! Please check your url to make sure it is
// the correct link!"
// so using the domain name as your "Home" link ensures that it
// will load the default index.php page every time! no errors!
$dispatch->init();
// now what happens if you put a form route in the view
// like the following?
// <form action="unknown"></form>
// <input type="hidden" name="test" value="some test value">
// </form>
// it will come here also because x1 = unknown, and x2 is null!
// here is the problem: the browser is confused!
// some browsers will load the default index.php and some browsers
// don't know what to do and display an error: Can't load the page!
// notice that we're talking about forms and not anchors!
// so the browser is confused!
// if it is an anchor it is probably okay and not confused!
// to solve this problem, for forms use the correct route:
// user/login, cart/addtocart, etc.
// so be aware of these scenarios!
// in other words, make sure you specify the correct route/link!
}
}
// handling the incoming instructions from the view!
// if the controller exists then call the controller
// also store the properties in the main application object to
// be used later: $this->base->x1
public function splitUrl()
{
// if you look in the .htaccess file you'll see this:
// RewriteRule ^(.*)$ index.php?url=$1 [L,QSA]
// check if the url GET parameter is set
// now the 'url' part is where we test for!
if (isset($_GET['url']))
{
// load the url into url variable
$url = $_GET['url'];
// trim the url to remove slashes on right:
// user/signup/id/guest/vip/
// becomes:
// user/signup/id/guest/vip
$url = rtrim($url, '/');
// break the url into fragments:
// $url[0] = 'user', $url[1] = 'signup', $url[2] = 'id',
// $url[3] = 'guest', $url[4] = 'vip'
// what happens if a user types in the url bar like:
// http://www.example.com ?
// splitUrl() will try to split the GET parameters and $url is null!
// in other words, splitUrl() cannot split the GET parameter:
// there is none!
// and the foreach ($url) loop below will return null as well!
// and therefore, x1, x2, x3 also will be null!
// now what happens if you put a link/route like the following?
// <a href="about">About</a>
// <a href="affiliate">Afilliate</a>
// <a href="signup">Signup</a>
// <a href="login">Login</a>
// it will split the url and $url contains an array of one element:
// $url[0] = 'about'
// $url[0] = 'affiliate'
// $url[0] = 'signup'
// $url[0] = 'login'
// and therefore, x1 = 'about', 'affiliate', 'signup', 'login'
// and x2 and x3 are null!
$url = explode('/', $url);
// load the url fragments as the object property variables
// as x1, x2, x3 ....
// in other words, set the main application's properties!
// notice that in PHP, you can declare a property on the spot
// and set it on the spot as well! very neat, huh?
// this is exactly what happens in the method set() below!
// you need to write a set($property, $value) in your main
// application controller class (Base) as well as a get()
//
// put the following two methods in your main base controller
// public function set($property, $value)
// {
// $this->$property = $value;
// }
//
// usage get():
//
// $base->get('x1');
//
// will return the controller, i.e.: user
//
// public function get($key)
// {
// if (isset($this->$key))
// {
// return $this->$key;
// }
// else
// {
// return null;
// }
// }
foreach ($url as $key => $value)
{
$key++;
// this is basically setting class Base's properties
// so that we can use them later. see init() above!
// later, anywhere, we can do this:
// $base->x1, $base->x2, $base->x3
// this will become:
// x1 = $value, x2 = $value, x3 = $value ....
$this->base->set('x'.$key, $value);
}
} // end if (isset($_GET['url']))
} // end splitUrl()
} // end class route
?>
Next is the dispatcher to dispatch the controller to the correct external controller.
Remember that there are two forms of controllers: internal controllers and external controllers.
In this case, the internal controllers are the class route and class dispatcher.
The external controllers are the controllers that actually doing the actual request to the models and as well as dictating to the views to display the views.
If you look in the method "user()" of the controller class "dispatcher" below, it creates an external controller by calling the createController() to create an external controller.
This is the manager who dictates to the programmers.
Remember that the manager only coordinates the job and doesn't do any heavy work at all! The heavy work is being done by the programmers.
As you can see below, the manager only asks the programmers to hand over the work by doing this: $base = new Base(). Now the manager knows nothing about what the programmers are doing inside class Base.
Now programmers all over the world can get to work on classes in their own seperate unique ways and none of them need to know what the others are doing. This is the seperation of concern of an MVC.
This example only shows one class or model; however, in a normal project large or small, there are lots of classes or models to be built and those classes or models can be given to groups of developers all over the world. And each group can work independently of one another without needing to know what the other groups are doing.
<?php
class dispatcher
{
public $base = array();
// now class dispatcher's init function
public function init()
{
// this method only contains two lines!
$this->base = new Base();
$this->base->render('index');
// that's it!
// the above call to render() tells the view to render
// the actual file in the 'view' folder!
// it is the controller telling the views to display the page
// view!
// the above call to render() will render the default front page:
// resource/view/index.php or index.html
// here is an example of render()
// method render() renders the view.
// this render() is incomplete as of now because I want you to
// implement your own version of render to suite your objective!
// how you implement your version of render() is up to you!
// but I suggest that you implement it using only two arguments:
// $this->base->render($view, $template);
// with $template, you might find it very useful to send in,
// say, a theme, or even a model!
// how you do it, it's up to you!
// you can make improvements to this barebone render() to make it
// more robust and powerful!
// notice that render() below, $template is an array and is
// initialized to null and you can call it like this:
// $this->base->render('index');
// $this->base->render('contact');
// $this->base->render('about');
// $this->base->render('affiliate');
// below, the first argument is the page: index.php or contact.php
// the second argument is the template or theme page or model or
// whatever!
// notice that you don't need more than two arguments!
// put the following render() code in your main application
// base class similar to the example class Base()
// public function render($view, $template[] = null)
// {
// // setting the view template to default theme or whatever!
// // I won't show you the example and leave it for you
// // to implement in your own unique ways!
// // this "if" block needs more work to suite your objective!
// if ($template == null)
// {
// // set it to default theme or whatever!
// $template = 'default_theme';
// }
// // right here where you can branch out to different
// // views/files/themes
// // you can branch out to tidbits of snippets of code
// // views as well
// // right here, you can implement code that looks for
// // certain view and files that resides in a folder
// // it's a very good idea to implement code that can
// // handle views in its own folder.
// // that way you can put certain views in certain folders
// // for modularity purpose!
// // as stated earlier, how you implement your render()
// // is up to you!
// // but here is one possible way of doing it:
// // you implement your first argument that can receive
// // two items: view/index
// // with 'view' being the folder and index being the file!
// // you can call it like this:
// // $this->base->render('view/index');
// // $this->base->render('affiliate/index');
// // $this->base->render('about/index');
// // $this->base->render('profile/index');
// // OR
// // $this->base->render('catalog/index', $template);
// // $this->base->render('cart/index', $template);
// // $this->base->render('admin/index', $template);
// // $this->base->render('product/index', $template);
// // I won't show the latter case and leave it to you to do!
// // now let's illustrate the first case!
// // right here inside this render() you can do this:
// if (strpos($view, '/'))
// {
// $view = explode('/', $view);
// // now $view is an array of two elements: a folder and a file
// // $view[0] = 'view', $view[1] = 'index'
// // $view[0] = 'affiliate', $view[1] = 'index'
// // $view[0] = 'about', $view[1] = 'index'
// // $view[0] = 'profile', $view[1] = 'index'
// // from there, you can branch out to display the view from
// // its own folder!
// // as far as the second argument is concern, it is very
// // much can be anything: a theme or a model or anything!
// // right here where you refer to the view files
// // stored in the directory:
// $file = "resource/$view[0]/$view[1]" . '.php';
// if (file_exists($file))
// {
// require_once $file;
// }
// else
// {
// echo ("View file <b>resource/$view[0]/$view[1]</b>" .
// '.php not found');
// }
// }
// else
// {
// // you need to put all of your view files in a folder
// // called 'view' or whatever folder name you desire!
// $file = "resource/view/$view" . '.php';
// if (file_exists($file))
// {
// require_once $file;
// }
// else
// {
// echo ("View file <b>resource/view/$view</b>" .
// '.php not found');
// }
// }
// } // end render()
// ***** END OF RENDER() *****
// you'll have to create a file called about.php and put it
// in the autoload directory!
// see my other tutorial called "how to autoload classes using SPL"
// do the same thing for the rest of these files:
// this is the manager telling the programmers to handover the task!
// maybe more appropriately the controller telling the view to
// display the model or data!
// the model is the the data to display: about.php
// the route for this method is: <a href="about">About<>
public function about()
{
$this->base->render('about');
}
// the controller telling the view to display the model or data!
// the model is the the data to display: affiliate.php
// the route for this method is: <a href="affiliate">Afilliate</a>
public function affiliate()
{
$this->base->render('affiliate');
}
// the controller telling the view to display the model or data!
// the model is the the data to display: signup.php
// the route for this method is: <a href="signup">Signup</a>
public function signup()
{
$this->base->render('signup');
}
// DIDO!
// the route for this method is: <a href="login">Login</a>
public function login()
{
$this->base->render('login');
}
// DIDO!
// the route for this method is: <a href="profile">Profile</a>
public function profile()
{
$this->base->render('profile');
}
// as you may know by the look of this controller class 'dispatcher',
// it is very cluttered if you have lots of conttollers/actions!
// it will make this class very hard to navigate and debug!
// a better solution is to do what I'm attempting to do below,
// and that is, create a controller method in your base/main
// application class similar to this example base class Base()!
// inside this main base class, you can create a controller method.
// this is my attempt to make this MVC application more robust and
// powerful by creating a controller instance and then call that
// external controller from here to execute that external controller!
// when a view sends a controller/action such as user/login
// it comes here and it looks for an external controller/action to
// route to by calling the createController() method below!
// remember that this class dispatcher is a controller but this
// controller can have other external controllers as well!
// sort of manager of managers: head manager having middle managers!
// I call them inner controllers and external controllers!
// put this method in your main application base class similar
// to Base()
// public function createController($controller)
// {
// // here, you put all of your controller files in folder:
// // controller
//
// // this will load a controller class file like these:
//
// // controller/UserController.php
// // controller/AdminController.php
// // controller/CartController.php
// // controller/MediaController.php
//
// // make sure to name your external controller files accordingly!
// // e.g., UserController.php, AdminController.php, etc.
//
// // the reason that you append the word 'Controller' to your
// // external controller files is to differentiate them from
// // other classes, say, 'model' and 'view'!
//
// // then in the external class definition, you can name your
// // external controller classes accordingly, e.g.,
//
// // UserController, AdminController, CartController, etc.
//
// // you can convert the first letter in $controller to uppercase
// // using function ucfirst()
//
// // ucfirst($controller)
//
// $file = "controller/$controller" . 'Controller' . '.php';
// if (file_exists($file))
// {
// require_once($file);
// $controllerObj = new $controller();
//
// // return an instance of the controller class back to
// // the caller!
// // see an example controller class user below!
// return $controllerObj;
// }
// else
// {
// echo ("$controller" . 'Controller not found.');
// }
// ***** end of createController() *****
// right here, you group all the action methods of class 'User'
// to call to: User->login, User->logout, User->profile, etc!
// don't mix up with function user() below with controller class
// 'User' later as in: createController('user')
// the route for this method user() could be something like this:
// <a href="user/login/id/guest/vip">Login</a>
// or just:
// <a href="user/login">Login</a>
// <a href="user/logout/id/guest/vip">Logout</a>
// or just:
// <a href="user/logout">Logout</a>
// <a href="user/profile/id/guest/vip">Profile</a>
// <a href="user/admin_login/id/guest/vip">Admin Login</a>
// <a href="user/admin_logout/id/guest/vip">Admin Logout</a>
// <a href="user/admin_singup/id/guest/vip">Admin Signup</a>
// <a href="user/forgot/id/guest/vip">Forgot Password<></a>
// <a href="user/usernamecheck/id/guest/vip">Check Username</a>
// <a href="user/emailcheck/id/guest/vip">Check Email</a>
// and they will come here!
public function user()
{
$x2 = $this->base->get('x2');
switch ($x2)
{
// the manager is asking the programmers to
// handover the tasks!
case 'login':
case 'logout':
case 'profile':
case 'admin_login':
case 'admin_logout':
case 'admin_singup':
case 'forgot':
case 'usernamecheck':
case 'emailcheck':
// right here, if any of the above case is met,
// it will come here to look for a specific
// controller action: $x2
// basically, $x2 is the action or controller
// method: login()
// we need to specify the external controller class as
// 'user' and it will route to that controller looking
// for an action method to execute!
// creating an external controller: 'user'
$this->base->createController('user')->$x2();
// you can pass the controller as a variable as well:
// $this->base->createController($x1)->$x2();
break;
default:
$this->init();
}
// as you can see, this is much more robust and powerful as it
// allows you to route to each controller class and to look for
// specific actions in that class!
// you can use this example method user() to do other external
// controller/action to make your MVC application more robust!
// notice that you can group these actions: about(), affiliate(),
// signup(), login(), profile() in a class of their own similar
// to the class 'User' and thus makes it more robust and powerful
// and less cluttered!
}
} // end class dispatcher
// as you can see, createController('external_controller_class') creates
// an instance of the external controller class!
// now you need to create those external controller classes!
// here is an example of the controller class User!
// this is the controller 'user'
// or if you want to differentiate your controller classes from
// other classes, you can append the word 'Controller' to the class
// name: 'UserController'
// see createController() example above for more detail!
// class User
// {
// // public $base;
// // $this->base = new Base();
// // this is the action 'login'
// public function login()
// {
// // remember that this is the controller/manager
// // and the manager doesn't do any heavy work!
// // so the manager usually asks the workers to
// // do the actual heavy work!
// // so you should never have to do any heavy programming
// // in any of your "external" controllers!
// // the controller should always asks the model to return
// // true or false whether the task is successfully
// // or not! that's all!
// // an example of that is the creation of class Base instance
// // above! as you can see, the controller/manager does
// // absolutely nothing in the form of heavy work!
// // the login credential: username and password
// // is available at the view via: HTTP REQUEST!
// // send it to the view: a login form!
// $this->base-render('login');
// }
// // this is the action "profile"
// public function Profile()
// {
// // remember that this is the controller/manager
// // and the manager doesn't do any heavy work!
// // so the manager usually asks the workers to
// // do the actual heavy work!
// // so you should never have to do any heavy programming
// // in any of your controllers!
// // the controller should always asks the model to return
// // true or false whether the task is successfully
// // or not! that's all!
// // an example of that is the creation of class Base instance
// // above! as you can see, the controller/manager does
// // absolutely nothing in the form of heavy work!
// // send it to the view to display the profile!
// $this->base-render('profile');
// }
// this is the controlller
// if you want to differentiate your controller classes from
// other classes, you can append the word 'Controller' to the class
// name: 'UserController'
// see createController() example above for more detail!
// class SomeOtherController
// {
// public $base = array();
// $this->base = new Base();
// // this is the action "someaction"
// public function SomeAction()
// {
// // remember that this is the controller/manager
// // and the manager doesn't do any heavy work!
// // so the manager usually asks the workers to
// // do the actual heavy work!
// // so you should never have to do any heavy programming
// // in any of your controllers!
// // the controller should always asks the model to return
// // true or false whether the task is successfully
// // or not! that's all!
// // an example of that is the creation of class Base instance
// // above! as you can see, the controller/manager does
// // absolutely nothing in the form of heavy work!
// // send it to the view to display the someview!
// $this->base-render('someview');
// }
} // end class dispatcher
?>
Notice that the manager does very little! All of the heavy work load is being done by the programmers.
Keep this analogy in mind as you work through the MVC pattern. There should not be any heavy work being done by the controllers. The controllers only need to know true or false. That's all! Nothing else!
For example, if you're programming a registration or login application, the model or models need to return only true or false if a user is successfully registered or logged in. Likewise, with other models, they need to return only true or false to the controller and nothing else.
For example, if a model is retrieving a bunch of products to be used in a catalog display in a view, the model can return true if the products are successfully retrieved from the database or false otherwise. For example:
<?php
/**
* retrieve the products from the database
*/
class Product
{
// constructor
public function __construct()
{
// constructor code logic);
}
// get the product
public function getProduct()
{
// code logic
// query the database: SELECT * FROM Product
// return the product to the controller as an array!
}
}
?>
In getProduct(), you need to retrieve the products from the database and return the products accordingly so that in the controller, you can just test to see if it returns any product or null. True or false!
In the controller, all it needs to be done is instantiating the model: $product = new Product().
$model = $product->getProduct().
Now the controller or manager can handover the product to the view.
You can send it to the view via a render() method: $this->base->render('catalog', ['model' => $model]).
Remember that the second argument of render() is an array; and therefore, you can send a model containing an array.
The trick is to test for the second argument for an array element: 'model' inside your render(). How you implement the second argument logic is up to you.
However, there is an easier way to send models to the view:
$this->base->set('model', $model).
Now the above line sets the property called 'model' to your base controller class similar to class Base() in this example.
Now using set() above, the controller or manager can handover the product to the view: render('catalog').
Notice that it is much simpler and there is no model attached to render().
Now inside the catalog view, you can retrieve that property like this: $catalog = $this->base->get('model').
Display the catalog. For example, inside the view 'catalog.php':
foreach ($catalog as $key => $value)
$key should be a product id and $value should be an array holding the product object: id, name, price, description, image, etc.
How you implement your view's render() is up to you. You can make improvement to the barebone render() code example shown earlier to make it more robust, like handling multiple themes and files.
Inside the barebone render() you can make it more robust and powerful by branching out to display snippets of views like sidebars flash display, ad flash display, and other content displays. See earlier code example for guidance.
Note that it is a good idea to specify the second argument of render() as an array: render($view, $template = array())
Please use the very popular shorthand array: render($view, $template = []).
This way, you can send all kinds of content to the view!
Note that you don't need more than two arguments in render() as the second argument handles all kinds of content to be sent to the view.
You can specify the second argument as an optional argument as well by doing this: render($view, $template[] = null).
By doing that you can send only the view that are simple views like about, contact, profile, etc, without using the second argument. For example:
$this->base->render('about'); // this will render the view/about.php page
$this->base->render('contact'); // this will render the view/contact.php page
$this->base->render('profile'); // this will render the view/profile.php page
As stated above, there should not be any heavy work being done by the controllers. All of the heavy work load should be done by the models.
The models should be autoloaded using SPL autoload and are grouped in their own folders. Likewise, for the views and controllers, they should be grouped in their own folders and autoloading them accordingly. See my other tutorials called "how to autoload classes using SPL."
To learn more about MVC pattern, please check out the Internet by Googling the term MVC or Model View Controller.
For a starter, here is a list of very good introductory tutorials on the Web that I found to be very good tutorials:
The MVC Pattern: PHP, MVC and Best Practices The MVC Pattern and PHP, Part 1 The MVC Pattern and PHP, Part 2 The MVC Pattern: An Introduction to the Front Controller Pattern, Part 1 The MVC Pattern: An Introduction to the Front Controller Pattern, Part 2For a more advanced pattern methodology, please check out MVVM (Model-View-ViewModel)
Advanced Pattern: The advantages of MVVM over MVCThere you have it: a very brief but useful introduction to MVC pattern.
You should be able to use this MVC pattern tutorial and build your very own sophisticated applications--large or small. From here, the possibilities are endless!
Have fun programming and don't forget to thank me later!
The following are just bonus MVC materials to help you understand the MVC concept further.
The following materials are taken from the tutorials mentioned in the links earlier.
It is possible to write a web application in PHP whose architecture is based on the MVC pattern. Let's start with a generic bare bones concept example.
Remember that there are three parts: M-V-C?
We'll start with 'M', which is the model.
The model is the data. If you recall from my tutorial earlier, the model is the programmers and the programmers do all the heavy work in manipulating the data. So data equals programmers. Keep that in mind!
What are we really trying to do here?
If you look in the code example below, it says $this->string = "MVC + PHP = Awesome!".
$this->string is a variable to hold data, hence model is all about data.
And the actual data is: "MVC + PHP = Awesome!".
Do you get the hang of it?
This example shows a very simple case of handling data. In most cases, you'll have to query the database to get the model. Yes, that is not a misstatement. In an MVC talk, it's a 'model' but in a human talk, it's a 'data'. Get used to talking about model being the data from now on!
<?php
class Model
{
public $string;
public function __construct()
{
// get the model. most cases, you'll do some database queries
// $this->string = 'SELECT * FROM someTable'
// remember that all the heavy work are being done right here in the model?
$this->string = "MVC + PHP = Awesome!";
}
}
?>
This is the view or 'V'.
The view is the display - showing the model to the user. Take a look at the function output(). It's main purpose is to output the data to the user. I really mean it outputs the model to the user.
Before it can output the model to the user, it has to get it first by way of the constructor. In other words, the model is passed to the view via the constructor.
Since the view needs the instruction from the controller as well, it also needs to pass the controller to the view as well.
Remember the controller? Or a manager? Maybe a manager who coordinates the tasks, perhaps?
<?php
class View
{
private $model; // this variable $model is for holding: "MVC + PHP = Awesome!"
private $controller;
public function __construct($controller, $model)
{
$this->controller = $controller;
$this->model = $model;
}
public function output()
{
// right here where it is very tricky!
// it tries to get the string: MVC + PHP = Awesome!" from the model in
class Model shown earlier!
$this->model refers to the private variable $model above!
->string refers to a public variable in class Model shown earlier!
basically, it returns the string: "MVC + PHP = Awesome!"
return "<p>" . $this->model->string . "</p>";
}
}
?>
Here is the controller or 'C'.
Remember the controller? Or a manager? Maybe a manager who coordinates the tasks, perhaps?
Remember that a manager/controller does very little work. The heavy work are being done in the model.
So what sort of tasks are to be performed by the controller?
If you look at the code below, all it does is taking a model and does nothing!
If you recall my tutorial earlier, I stated that there are two controllers: inner controller and external controller - sort of top manager and middle manager interacting with one another to complete the tasks.
This controller, you can say that it is the top manager. Later on, you'll see another controller or middle manager who responses to this top manager and then that middle manager coordinates the final tasks to tell the view to display the model to the user.
<?php
class Controller
{
private $model;
public function __construct($model)
{
$this->model = $model;
}
}
?>
We have our project started with some very basic classes for each part of the pattern. Now we need to set up the relationships between them.
This is the middle manager who coordinates the final tasks.
As you can see, neither the top manager nor the middle manager does any work at all. All they do is just coordinate the final task.
<?php
$model = new Model();
$controller = new Controller($model);
$view = new View($controller, $model);
echo $view->output();
?>
Here is their explanation of the code above:
As you can see in the example above, we don't have any Controller-specific functionality because we don't have any user interactions defined with our application. The View holds all of the functionality as the example is purely for display purposes.
Let's now expand the example to show how we would add functionality to the controller, thereby adding interactivity to the application:
<?php
class Model
{
public $string;
public function __construct()
{
// get the model. most cases, you'll do some database queries
// $this->string = 'SELECT * FROM someTable'
$this->string = "MVC + PHP = Awesome, click here!!";
}
}
?>
<?php
class View
{
private $model;
private $controller;
public function __construct($controller, $model)
{
$this->controller = $controller;
$this->model = $model;
}
public function output()
{
// right here, it returns an anchor link to the caller!
// remember what $this->model->string returns?
// a hint: "MVC + PHP = Awesome, click here!!"
// basically, when you click on the anchor link it will call a
// function named click()
// action=click refers to a controller function named 'click'
// see class Controller with function named 'click' below!
// you can format your anchor link like this as well and you can
// include as many GET parameters as you want using '&'. for example:
// '<a href="http://www.example.com/index.php?action=click¶m1=value1">' .
// $this->model->string . "</a>"
return '<p><a href="mvc.php?action=click">' . $this->model->string . "</a></p>";
}
}
?>
<?php
class Controller
{
private $model;
public function __construct($model)
{
$this->model = $model;
}
public function click()
{
$this->model->string = "Updated Data, thanks to MVC and PHP!";
}
}
?>
We've enhanced the application with some basic functionality. Setting up the relationship between our components now looks like this:
The following code is the main base application and it is analogous to a
class called Base() in my MVC example shown earlier.
It is the main application base class similar to the example class Base()
shown in my other tutorial called 'How to autoload classes using SPL'.
See class Dispatcher, particularly the method render() about explanation
on Base() class.
In other words, put the following code in your main application base class similar
to class Base() shown in my other tutorial called 'How to autoload classes using SPL'.
<?php
$model = new Model();
// this is similar to a code that creates a controller class: see createController()
$controller = new Controller($model);
$view = new View($controller, $model);
if (isset($_GET['action']) && !empty($_GET['action']))
{
// once you instantiated a controller class, you can use that
// controller instance ($controller->) to call its action method via: $_GET['action']
// so if you have a controller class called CartController, and its
// action method called addToCart(), then the code below would be:
// CartController->addToCart()
// provided that you change the action method $_GET['action']
// to $_GET['addtocart']
// this is similar to a code that creates a controller class: see createController()
// and it looks something like this:
// creating an external controller: 'user'
// $this->base->createController('user')->$x2();
// you can pass the controller as a variable as well:
// $this->base->createController($x1)->$x2();
// notice that: $this->base->createController($x1) being the $controller->
// and $x2() being the $_GET['action']()
// notice that the {} wrapping around $_GET is analogous to 'echo'
$controller->{$_GET['action']}();
}
// this will echo out an anchor link:
// <a href="mvc.php?action=click">MVC + PHP = Awesome, click here!!</a>
// now all you have to do is click on the anchor link to see the effect!
echo $view->output();
?>
Run the code and when you click on the link you'll be able to see the string change its data.
Conclusion
We've covered the basic theory behind the MVC pattern and have produced a very basic MVC application, but we still have a long way to go before we get into any nitty-gritty functionality.
This concludes MVC extra bonus materials!
access control
: public, protected, and privatepublic, protected, and private are visibility clauses (similar to static and final). A visibility
clause is a term used to describe the access control
in certain part of the code. It's like a key to a toolbox where you are allowed to use certain tools for certain projects only if you have the key to open it. It is restricted to use certain tools. So you can't just go grab the tools and use freely; you have to have certain keys to open the toolbox and use the tools.
In programming, we have visisibility clauses
or visibility controls
to allow you to restrict certain part of the code to be accessible to certain programs.
Visisibility clauses
or visibility controls
allow certain part of code to be protected from outside abuses. Visisibility clause
or access control
is about controlling visibility of the methods
and variables
from outside classes usage. The visibility of the code elements are determined by their access control
specifications or clauses
: public, protected, and private.
Note: the term visisibility clause
or access control
mean the same thing and both are being used interchangibly.
protect
" a method
or variable
from unauthorize references, you use the three levels of access control
visibility: public, protected, and private.
A class is like an island onto itself where only people on the island can get access to the resources residing on that island. Because of this inaccessibility that a method of distinguishing who is allowed to get on and who is not allowed to get on -- and what level of restrictions certain methods
and variables
are placed on -- was developed.
The three-level of restrictions was developed to allow access control of the methods
and variables
.
Note: Visibility access control
only concern with methods
and variables
and nothing else. Variables
sometimes referred to as property variables
or just plainly properties
. So keep this in mind as you go through the descriptons:
methods
and variables
declared as public can be accessed everywhere.methods
and variables
declared as protected can be accessed only within the class itself and by classes derived from that class.methods
and variables
declared as private may only be accessed by the class that defines the methods
and variables
. In other words, ONLY
the class that defines the private methods
and variables
can access these private methods
and variables
[that they defined themselves].
All other classes cannot access these private methods
and variables
[of another class or classes]. They can ONLY
access their own private methods
and variables
.
methods
and variables
declared without any explicit visibility keyword are defined as public.Before we get into the main visibility access control
: public, protected, and private, let's get this one nagging issue out of the way that seems to get a lot of people confused, and that is, the use of keyword var. For example:
<?php
class MyClass
{
/** declaring MyClass' properties: **/
/**
* as you can see below, we declare a property called $make as 'public'
* using the keyword 'var'.
* this is the same as declaring: public $make
*/
var $make; // declaring a property as 'public'
// for non-public properties, you use the appropriate clause, i.e., protected.
protected $model;
// for non-public properties, you use the appropriate clause, i.e., private.
private $color;
}
?>
The keyword var was the original design to signify the property as a public variable. So instead of having to specifically declaring a property using the keyword public, all we had to do was using the keyword var followed by the variable name and we had a public property variable. That was in the old days!
Then the folks at PHP decided to get rid of the old legacy mistake and instituted the proper way of doing things by replacing the keyword var with the keyword public starting in PHP 5.0. Then an uproar erupted and created a lot of confusion. It lasted for a couple of versions until it was too much of a headache to bear and they decided to put back the old legacy style by re-instituting the keyword var to its original style starting in PHP 5.3.
Since version 5.3 and onward, you can actually use either of the two keywords and they will all work just fine. However, they really stress/encourage all programmers to use keyword public and discourage the use of keyword var.
Visibility Access Control
: Public, Protected, and PrivateLet's see how to use the visibility access control
: public, protected, and private. For example:
<?php
/**
* declaring class Vehicle's properties only -- no methods
*/
class Vehicle
{
// declaring class Vehicle's properties:
public $make; // declaring a property as 'public'
protected $model; // declaring a property as 'protected'
private $color; // declaring a property as 'private'
}
?>
Now to see the effect of the visibility clauses in action, consider this:
<?php
/**
* now we're creating another class outside of class Vehicle.
* this class will try to get through class Vehicle's visibility control.
* let's see if this class can get through class Vehicle's visibility control.
*/
class Ford
{
// creating an instance of class Vehicle:
$obj = new Vehicle();
// now try to get through class Vehicle's visibility control.
/**
* this reference is fine because the property is declared as
* 'public'. so class Vehicle allows class Ford to use its property.
*/
$obj->make = 'Ford';
/**
* this reference will cause a 'fatal error' because the property is declared as
* 'protected'. so class Vehicle didn't allow class Ford to use its property.
*/
$obj->model = 'F150';
/**
* this reference will cause a 'fatal error' because the property is declared as
* 'private'. so class Vehicle didn't allow class Ford to use its property.
*/
$obj->color = 'grey';
}
?>
As you can see, declaring methods and properties as protected and private restricts outside classes like Ford
from using its properties.
methods
and property variables
. For example:
<?php
/**
* now we're adding methods to class Vehicle.
*/
class Vehicle
{
// declaring class Vehicle's properties:
public $make; // declaring a property as 'public'
protected $model; // declaring a property as 'protected'
private $color; // declaring a property as 'private'
/**
* declaring class Vehicle's method as 'public'
* notice that declaring a method without the visibility clause has
* the same effect as 'public'. so the 'public' clause can be omitted!
*/
public function setMake($make)
{
// assigning a value to class Vehicle's property
$this->make = $make;
}
// declaring class Vehicle's method as 'protected'
protected function setModel($model)
{
// assigning a value to class Vehicle's property
$this->model = $model;
}
// again, declaring class Vehicle's method as 'private'
private function setColor($color)
{
// assigning a value to class Vehicle's property
$this->color = $color;
}
}
?>
Now to see the effect of the visibility clauses in action, consider this:
<?php
/**
* now we're creating another class outside of class Vehicle.
* this class will try to get through class Vehicle's visibility control.
* let's see if this class can get through class Vehicle's visibility control.
*/
class Audi
{
// creating an instance of class Vehicle:
$obj = new Vehicle();
// now try to get through class Vehicle's visibility control.
/**
* this reference is fine because method setMake() was declared as
* 'public'. so class Vehicle allows class Audi to use its method.
*/
$obj->setMake('Audi');
/**
* this reference will cause a 'fatal error' because setModel() was declared as
* 'protected'. so class Vehicle didn't allow class Audi to use its method.
*/
$obj->setModel('A6');
/**
* this reference will cause a 'fatal error' because setColor() was declared as
* 'private'. likewise, class Vehicle didn't allow class Audi to use its method.
*/
$obj->setColor('grey');
}
?>
As you can see, declaring methods
and properties
as protected and private can be accessed only from within the class that those methods
and properties
are defined.
protected properties or methods can be accessed within the class and by classes derived from that class
'. What does that mean?
Let's take a look at the same class definition Vehicle but this time we will extend this Vehicle class further and see if child classes can get access to class Vehicle's visibility control:
<?php
class Vehicle
{
/**
* declaring class Vehicle's properties as private:
* notice that these two 'private' properties can be accessed only from inside
* this Vehicle class. classes that extends from Vehicle cannot access these
* two private properties.
*/
private $price;
private $tax;
/**
* declaring class Vehicle's constructor as 'public'
* notice that declaring a method/constructor without the visibility clause
* has the same effect as 'public'. so the 'public' clause can be omitted!
*/
public function __construct($price, $taxRate)
{
/**
* assigning values to class Vehicle's properties
* 'private' properties can be accessed only from inside this Vehicle class
*/
$this->price = $price;
$this->tax = $taxRate;
}
/**
* if calculateTax() was declared as 'private' no child class can access this
* private method. the only method that can access this private method is from inside
* the constructor using $this, for example: $this->calculateTax()
*
* let's be clear about this: ONLY if calculateTax() is declared as 'private'
*
* let's clarify that statement earlier a little bit:
* 'the only method that can access this private method is from inside the constructor'
*
* that statement is only true if this Vehicle class has only the constructor method as
* it stands right now.
* if there are more methods to be had, regardless of their visibility clause,
* then they all can access to these private properties as well as other private methods
* of class Vehicle. so 'private' means ONLY within the class itself and not outside of
* the class. this means that any method within the class can access 'private' properties
* and methods declared within the class.
* so make note of that!
*
* this means that no other class or classes even child class or classes of Vehicle can
* get access to class Vehicle's private properties and methods.
*
* however, calculateTax() is declared as "protected" and therefore child classes of
* Vehicle can get access to calculateTax() just fine!
*
* did you remember a phrase that goes like this [?]:
* 'protected can be accessed only within the class itself and by classes derived from
* that class'.
*
* this is exactly what that phrase means!
*
* here is the 'protected' method calculateTax()
*/
protected function calculateTax()
{
/**
* now since this method is declared as 'protected' child classes that extend
* from this parent class Vehicle can get access to this 'protected' method.
* no other classes can get access to this 'protected' method.
*/
// getting a tax
$tax = $this->$price x $this->$taxRate;
return $tax;
}
}
?>
Now to see the effect of the protected or private visibility clause in action, consider this:
<?php
class Ford extends Vehicle
{
public function getTax()
{
// getting a tax from parent class Vehicle
// calling a protected method, is it legal?
// see below and an explanation later as well!
$tax = $this->calculateTax();
return $tax;
/**
* the 'protected' rule: child classes that extend from a parent class with
* methods declared as 'protected' can get access to those 'protected methods.
* no other classes can get access to those 'protected' methods.
*/
}
}
?>
Now to see the effect of the visibility clauses in action in child class Ford, consider this:
<?php
/**
* now we're creating another class Audi outside of class Vehicle and Ford.
* this class Audi will try to get through Vehicle's and Ford's visibility controls.
* let's see if Audi can get through class Vehicle's and Ford's visibility controls.
*/
class Audi
{
// creating an instance of class Ford which extends Vehicle:
$obj = new Ford('25000', '0.07');
/** now try to get through class Ford's and Vehicle's visibility controls. **/
/**
* calling $obj->getTax() is OK because Ford's method getTax() was declared as
* 'public'. so class Ford allows class Audi to use its method getTax().
* now, in turn, getTax() calls calculateTax() (which is declared as 'protected') from
* within the derived class Ford.
*
* a public method getTax() calls a protected method calculateTax()!
*
* is it legal for a public method to call a protected method?
*
* did you remember a phrase that goes like this [?]:
* 'protected can be accessed only within the class itself and by classes derived from
* that class'.
*
* '.... by classes derived from that class' means Ford derived from Vehicle.
*
* getTax() calls calculateTax() from inside class Ford.
* class Ford is a derived class from Vehicle.
*
* as you can see, it is OK for a public method to call a protected method from
* inside the derived class, in this case, Ford.
*/
$obj->getTax(); // calling $obj->getTax() is OK because getTax() is 'public'
}
?>
Let's re-cap what the three visibility control are:
public just the word implies, it is open to the public and anybody can get access to these public methods
and properties
.
protected just like the word implies, it is protected within the family and relative circle, and others outside of the family and relative circle cannot get accessed to the protected methods
and properties
. This means that child class (or classes) methods
and properties
declaring as public can get access to parent class methods
and properties
declared as protected.
private just like the word implies, it is a private matter/affair and it is not open to the public or to their own descendant classes either. This is very strict even their own relatives and descendants can't even get accessed to methods
and properties
of a private class.
methods
and properties
inside a private class can only be accessed from inside that private class by their own member methods
and properties
. Child class or classes of the private class cannot get accessed to their own parent's methods
and properties
. That is very harsh!
So the key to remembering these three visibility controls is that, just think of them in term of real life examples like family and relatives and strangers and associate each scenario accordingly.
Another point is, to memorize protected first and leave the other two alone.
In other words, don't try to memorize the other two and only try to memorize protected very good. That way, you don't get them mixed up so easily.
Just think that protected is a protection within the family and relative, and descendants cycle and anybody outside of the cycle cannot get accessed to protected methods
and properties
.
Parent methods (such as constructors) can be overridden by child classes. To override parent methods, just redefine the parent methods (using the same name) in the child classes. For example, in class Vehicle
shown earlier in the previous section, it has a constructor with two argument parameters: __construct($price, $taxRate) and a protected method called calculateTax().
You can define a child class called Toyota that overrides and extends class Vehicle to contain more constructor's argument parameters. Let's create a child class that has a constructor with two additional argument parameters in addition to the two argument parameters that parent class Vehicle already has. For example:
<?php
class Toyota extends Vehicle
{
// declaring class Toyota's properties as private:
private $rebate;
private $carbonTax;
// declaring class Toyota's constructor with two additional parameters
public function __construct($price, $taxRate, $rebate, $carbonTax)
{
/**
* assigning values to class Vehicle's properties
* $this refers to class Vehicle's properties
*/
$this->price = $price;
$this->tax = $taxRate;
/**
* assigning values to class Toyota's properties
* $this refers to class Toyota's properties
*/
$this->rebate = $rebate;
$this->carbonTax = $carbonTax;
}
protected function calculateTax()
{
// getting a tax
$tax = $this->$price x $this->$taxRate + $this->carbonTax - $this->rebate;
return $tax;
}
}
?>
As you can see, the __construct() and calculateTax() methods in the child class (Toyota) override the __construct() and calculateTax() methods in the parent class (Vehicle).
Now to see the effect of the override methods in action in child class Toyota, consider this:
<?php
/**
* now we're creating another class Ford outside of class Vehicle and Toyota.
*/
class Ford
{
// creating an instance of class Toyota which has four parameters:
$obj = new Toyota('25000', '0.07', '5000', '2500');
// call the newly inherited Toyota's method calculateTax()
$obj->calculateTax();
}
?>
The RSA is a three-letter acronym derived from the names of its inventors at MIT in the 1970s using their last name's first letter as an acronym: Ron Revest, Adi Shamir, and Leonard Adleman.
The RSA encryption is a military-grade encryption scheme that is being widely used throughout the world, especially in banking applications and other top secret applications.
The RSA uses two keys: one called a public key and another called a private key. We'll discuss about keys later. For now, let's discuss about prime numbers.
The RSA uses prime numbers to create keys to encrypt and decrypt information.
For those of you who are not math inclined, or those who are not really into the historical and theoretical aspects of the RSA encryption, feel free to jump ahead to the implementation section.
For the rest, this section is probably of most significance (and of most importance) to those of you who are working with encryption or security in general. Having a detailed knowledge of how things really work (and why) is essential if you intend to keep your security systems one step ahead of hackers.
Prime numbers have been of interest since the ancient Greek philosophers. However, they were not of interest for theoretical purposes until the latter half of the twentyth century: the 1960s and 1970s when computer technology was beginning to catch fire.
Researchers saw the vulnerability of the information age that computer technology brought and they began to find ways to make the information age secure. A group of researchers at MIT, namely Ron Revest, Adi Shamir, and Leonard Adleman, came on top and their fruit of labor is now being used widely throughout the world.
Let's start with the simplest definiton of a prime number. Prime numbers were discovered by Euclid, sometimes called Euclid of Alexandria.
Euclid was an Ancient Greek philosopher who was born in 300 BC. He was a super, super brilliant mathematician who contributed to the world of mathematics in epic proportion.
In the book VIII of Elements, Euclid defined a prime as a number that has no whole-number divisors other than 1 and the number itself. A few examples of prime numbers would be 2, 3, 5, 11, 13, etc.
As you can see, neither 2, 3, 5, 11, or 13 are divisible by any number other than 1 and itself.
On the other hand, a number that is not a prime is said to be a composite.
Another important definition is called relative prime. But some textbooks call it coprime. I call it relative prime.
A prime number is considered a relative prime to any other number if it does not divide that number. Make note: It does not divide that number! That number is not divisible by a prime!
In other words, a prime number has some relative numbers out there. It has lots of relatives out there. Somewhere in the world of numbers, there are numbers that are relative to this prime number.
Sort of saying a person born without knowing how many relatives he/she has in the world and that person needs to go out and find his/her relatives out there in the world.
The same thing is also true for prime numbers: They need to go out and find their relatives among the numbers in the set.
A prime number cannot divide a number if that number is considered to be a relative prime to a prime number.
This is sort of saying: A person out there whose one or both of his/her parents are not the same as the parent or parents of the person seeking to find relatives CANNOT be a relative to the person seeking to find relatives.
A simplier way of say is that, a person has to share of at least one parent with another person in order to qualify as a relative to that person.
Let's put it this way: If a prime number p is a relative prime to a number n, then: n mod p is not equal to zero. The two numbers are not divisible by one another. We can say that p is a relative prime to a number n or vice versa.
Note: mod is a remainder division function representing modulus operation. So the goal of mod is to return the remainder of a division. For example, 4 mod 2 = 0, 5 mod 2 = 1, 10 mod 5 = 0, and 10 mod 3 = 1 (because 10 divided by 3 resulted in the quotient of 3 with the remainder of 1.)
So if n mod p is equal to zero, it means that n is divisible by p. But n cannot be divisible by p in order to be considered as a relative prime number to p.
Knowing that, we can basically formulate the following three rules or theories or propositions as Euclid called them.
If a prime number p divides a product m * n (with m * n means m multiplies n), then p divides at least one of the two numbers m or n. See proposition 1 illustration below.
By the way, in mathematics, a product is usually written as m x n as well as mn and as well as m.n, too. The latter one with a dot "." notation.
So all four forms: m x n, m * n, mn, and m.n are all valid forms of a mathematical product.
You will see all of the above mathematical forms throughout this tutorial, particularly using parentheses to group multiple entities, for example:
(p - 1)(q - 1) = (p - 1) x (q - 1) = (p - 1) * (q - 1) = (p - 1) . (q - 1)
Every number can be prime or else can be expressed as a product of prime in a way unique, apart from the order in which they are written.
This uniqueness is the key to the RSA cryptography.
A product of prime numbers will result in a prime number as well.
There are indefinitely many prime numbers (in the world of whole numbers.)
Okay, we have three propositions to prove, so let's lay them out one by one and then try to prove them:
Proposition 1:
If a prime number p divides a product mn,
then p divides at least of the two numbers m, n.
Proof:
Let the two numbers m and n multiplied by one another to make another
number o (letter o), and let any prime number p divides o.
Now we must prove that p divides m or n.
Let's assume that p does not divide m, therefore, p and m are relative primes.
Remember the definition of relative prime?
Now let's make another number e such that:
e = mn div p (we could use '/' instead of div as well)
(note: e is the number of units that p divides mn.)
(Make note: div and not mod.)
(div is a division function -- the same as '/'.)
Since p divides mn according to e, then pe = mn.
Therefore, p/m = n/e.
But p is a relative prime to m.
Therefore, they are the least of those that have the same ratio with them.
And the least divides the numbers that have the same ratio (p/n and m/e).
That is, p divides n (and m divides e.)
Similarly, we can also prove that if p does not divide n, then it must divide m.
Next up is Proposition II.
Proposition II is also known as the Fundamental Theorem of Arithmetic.
We'll prove Proposition II in two steps.
First, we can prove that a number can always be factored into primes, and then, secondly, we'll show that this process is unique; that is, there is only one prime factorization for each number.
This uniqueness is the key to the RSA cryptography.
See conclusion for similar statement at the end of Proposition II discussion for this second step.
Those are the two-step processes we are going to have to work through.
Proposition 2:
Every natural (or whole) number is either prime or can be uniquely factored as
a product of primes in a unique way.
Proof
Let's prove this using contradiction.
Let's assume that there are numbers that cannot be written as a product of primes.
Therefore, there must exist the smallest of such numbers; and we'll call it n.
By definition, n must be a natural number greater than 1.
'Nautral' means 'whole' and not fractional number.
So n = ab where a and b are natural numbers such as
a > 1 and b < n.
Therefore, a and b are smaller than n, so a and b can be factored into primes.
For example: n = (a - 1)(b - 1)
By substitution, n can be factored by primes.
This contradicts the assumption that there exist composite numbers that cannot be
factored into primes.
Conclusion: All natural numbers are either primes or can be written as a
product of prime numbers.
Now let's prove that this product is unique, again using contradiction.
This is the second step.
Let's assume that there are numbers that can be factored into primes in at least
two distinct "unique" ways.
Then, there must exist the smallest of such numbers, n,
where n can be represented by:
n = p1p2p3p4p5p6.....pk
OR
n = q1q2q3q4q5q6.....qk
Now let's select one of the members, say, p1.
We can say that p1 divides n, and, therefore,
it divides q1q2q3q4q5q6.....qk as well.
That means that n / p1 = q1q2q3q4q5q6.....qk / p1
But from Proposition I, if p1 divides the product q1q2q3q4q5q6.....qk,
then, p1 must divide at least one of its members, say,
q1 / p1
OR
q2 / p1
OR
q3 / p1
OR
q4 / p1
OR
qk / p1
Since all members on the right side of the equation (p1p2p3p4p5p6.....pk and
q1q2q3q4q5q6.....qk) are primes,
we can say that for a number qj (with 1 ⋜ j ⋝ n),
the following equality holds:
p1 = qj
We can, without loss of generality, assume j = 1
Therefore, p1 = qj
The result of n / p1 is a number smaller than n, and, consequently,
from our initial assumption,
it cannot be factorized in more than one unique ways.
It can only be factorized in one unique way!
Therefore, the consequences p2.....pk and q2.....qk contain the same primes,
possibly different only in their order.
Conclusion: There is only one way to factorize a number into primes.
This uniqueness is the key to the RSA cryptogrophy.
Well, if it wasn't the uniqueness property of the prime,
the RSA cryptography would have not been invented and
the crytography landscape of the world would have been
a lot different than today's environment.
So the uniqueness property of the prime made the RSA cryptography possible.
Proposition 3:
There are indefinitely many prime numbers.
Proof
Let's start with the list: p1, p2, p3, ..... of all known primes.
We must prove that this list continues forever because proposition III states
that there are indefinitely prime numbers out there.
Let's assume that we have listed all primes up to some pm.
Now consider a number p such as:
p = p1p2p3....pm + 1
Note: that is pm + 1 and not pm + 1. Be careful to not confuse the two.
Note that p1p2p3.... means a product of multiple primes.
Likewise, p1p2 means a product of two primes.
If p happens to be a prime,
then p is a prime bigger than pm (because of the product)
and the list can continue (note that p might not be the next prime after pm,
in which case, p cannot be taken to be pm + 1).
If p is not a prime,
then it must be evenly divisible by a prime (Proposition 2).
But none of the primes p1p2p3....pm divides p.
If you carry out such division, you always end up with a remainder of 1.
Therefore, p must be divisible by a prime bigger than all primes up to pm.
Conclusion: We can always find a bigger prime for any given list p1p2p3....pm.
In other words, the list of primes continues forever because there are
indefinitely prime numbers out there.
Taken together, the first two propositions form the building blocks of all natural (or whole) numbers, much like the physicist's atoms.
Knowing the prime number factorization of a number gives complete knowledge about all factors of that number.
Now that we've learned some of the fundamental properties of prime numbers, we need to learn how to find them, and -- most importantly -- how to prove that they are in fact primes.
How do we go about in finding primes?
There are many ways to find primes, and their efficiency usually depends on the size of the primes in which we are interested in, or on the probability of these numbers truly being primes.
One popular method of finding primes is called Sieve of Eratosthenes, which was invented by an ancient Greek philosopher named Eratosthenes in 280 BC.
To verify that n is a prime, follow this two-step process:
Here is a PHP code fragment to list the numbers from 2 to n:
<?php
$n = 2147483647;
$a = array();
$a[0] = 0; // we know that this is not a prime
$a[1] = 0; // we know that this is not a prime
// we start with 2 since 0 and 1 have already been initialzied above
// as you can see, it loops through $n = 2147483647 which
// takes some time to loop through!
for ($i = 2; $i < $n + 1; $i++)
{
// initialize all array indexes $a to 1 up to $n
// so $a[2] = 1, $a[3] = 1, $a[4] = 1, $a[5] = 1, ...
$a[$i] = 1;
}
?>
So you start with the smallest number, which is 2, and work your way upward to n.
Then you eliminate all multiples of 2 up to n. For example, what is left is this: 2, 3, 5, 7, 11, 13, ......, n.
Notice that 15 is an odd number but it is not a prime number because in the definition of prime stated earlier, it says a number cannot be divided by another number and 15 can be divided by 3 (which is 5); and therefore, 15 fails the definition of prime.
Likewise, 9 is not a prime number either because 9 can be divided by 3 (which is 3); and therefore, 9 fails the definition of prime as well.
Here is a PHP code fragment to eliminate multiples of 2 up to n:
<?php
$p = 2;
while ($p < $n)
{
// step through multiples of 2
$j = $p * 2;
// variable $n is an aribitrily number you supply!
while ($j <= $n)
{
// eliminate multiples of two up to $n
// and we know that these are not primes
// so $a[4] = 0, $a[6] = 0, $a[8] = 0, $a[10] = 0, ...
$a[$j] = 0;
$j += $p;
} // end while ($j <= $n)
do
{
// $p = 3, 4, 5, 6, 7, 8, 9, 10, 11, .... $n
$p += 1;
}
while ($a[$p] != 1)
} // end while ($p < $n)
?>
So now what is left is this: 2, 3, 5, 7, 11, 13, ......, n.
So what do these numbers in the list that were not eliminated mean?
Well, we'll look at the definition of prime again, and it goes like this: A prime is a number that has no whole-number divisors other than 1 and the number itself.
So the numbers in the list are prime numbers because they are not divisible by any other number other than 1 and themselves. So 2, 3, 5, 7, 11, 13 are prime numbers.
That's all you have to do to find prime numbers.
Although the numbers resulting from this method are sure to be primes, this algorithm is very slow and has exponential complexity, meaning it runs exponentially in the number of digits in the number n. As you can see in the fragment code illustration above, it loops through n = 2147483647 which takes some time to loop through.
Anyhow, let's go ahead and create a function to generate prime numbers using Sieve of Eratosthenes method illustrated above.
Let's put the whole pieces of code illustrated above together to form a complete code.
Here is an implementation of the Sieve of Eratosthenes:
<?php
/**
* finding primes using Sieve of Eratosthenes
*/
public function prime($n)
{
$a = array();
$a[0] = 0; // we know that this is not a prime
$a[1] = 0; // we know that this is not a prime
$p = 2;
// we start with 2 since 0 and 1 have already been initialzied above
for ($i = 2; $i < $n + 1; $i++)
{
// initialize all array indexes $a to 1 up to $n, for example:
// $a[2] = 1, $a[3] = 1, $a[4] = 1, $a[5] = 1, ...
$a[$i] = 1;
}
while ($p < $n)
{
$j = $p * 2;
while ($j <= $n)
{
// eliminate a multiple of two up to $n
// and we know that these are not primes, for example:
// $a[4] = 0, $a[6] = 0, $a[8] = 0, $a[10] = 0, ...
$a[$j] = 0; // set $a[4] = 0
$j += $p; // now increase $j by 2
} // end while ($j <= $n)
// here, we're looking for primes
do
{
// $p = 3, 4, 5, 6, 7, 8, 9, 10, 11, .... $n
$p += 1;
}
while ($a[$p] != 1)
} // end while ($p <= $n)
$k = 0;
$prime = array();
// iterate through n again, but this time we're only
// looking to pick out only primes
for ($i = 2; $i < $n + 1; $i++)
{
// test to see if any of array index $a = 1 up to $n
// if $a = 1 then it is a prime!
// so store it in array $prime for later retrieval
if ($a[$i] != 0)
{
$prime[$k] = $a[$i];
$k++;
}
}
return $prime;
} // end function prime($n)
/**
* prime() above can be called like this:
*
* $n = 50;
*
* $p = prime($n);
*
* foreach ($p as $value)
* {
* echo $value . " ";
* }
*
* output: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
*
* or if $n = 100;
*
* output: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
* 53 59 61 67 71 73 79 83 89 97
*/
?>
Here is another implementation of the Sieve of Eratosthenes that I want to illustrate. The code illustrated above and the following code (below) will achieve the same result, so that you can pick and choose to use at your own preference.
I want to illustrate that the code above is a tidbit slower than the one below; because, as you can see, the code above has four loops that loop from 2 to n, while the one below has only three loops (but four if you count the array_fill() loop, too).
The code above, I could have chosen to use array_fill() instead of the for() loop and both codes would have achieved the same performance. However, I chose to use for() loop just to illustrate that there are many ways to achieve the same result and also to point out that there are performance discrepancies between the two.
In the end, there isn't much meaningful differences in performance between the two -- only the one below is a very tiny, slightly faster only because of the use of the array_fill().
Because of the "computationally intensive" problem, it is generally a normal practice to generate primes randomly rather than using loops (four loops in this case).
In other words, randomly choose a number and then test that number for prime. That way it can be done without loops or fewer loops.
Use Fermat's Little Theorem to test for prime. See a section called Primality Test a little bit later.
If you don't want to use Fermat's Little Theorem to test for prime, it's not the end of the world to use loops (as my illustrations show). As a matter of fact, lots of people have done so for decades without using Fermat's Little Theorem.
However, wise guys tend to choose a random number, say, 3754 (or any number), and test it for prime. That is the quickest way to create prime numbers for your RSA applications.
If you want to use random primes, here is one way to do it.
You could use the Sieve of Eratosthenes code illustrated in this tutorial to create a list of prime numbers and store them in a file or database or some other storage mediums. See my code later about using a json file to store keys.
That way, you don't have to worry about taking too long to create prime numbers on the go, because you already created them and tested them for primes before hand.
Here is one way to do it:
<?php
/**
* First, you have to create primes using Sieve of Eratosthenes method.
* Second, store them in a file, database, or some other mediums.
* Third, when you need random prime numbers, just retrieve them from
* the storage device you created in the second step.
*
* This way, you don't need to create prime numbers on the fly as most
* wise guys often do!
*
* Here is one way to do it:
*/
// retrieve prime numbers from a storage device
// and place them in an array, for example:
$prime = array();
// assuming you're retrieving them from a database
try
{
// assumming $conn is an instance of a PDO
$stmt = $conn->prepare("SELECT prime FROM primetable");
/**
* retrieve prime numbers from the database
* and place them in an array variable: $prime
*/
$prime = $stmt->execute();
}
catch (PDOException $e)
{
echo 'ERROR: Cannot select data from the database: ' . $e->getMessage();
}
// mimicking a random prime number generator
// this example assumes we're working with
// 201 prime numbers: 0 to 200
do
{
$i = rand(0, 200);
$j = rand(0, 200);
$p = prime[$i];
$q = prime[$j];
}
while ($p == $q) // if p == q, keep looking!
// when p and q are distinct, we stop looking and keep them!
// now you can use p and q to calculate your RSA algorithm!
// you might want to put this fragment of code in a function
// and modify it slightly to return p and q
// so that you can call it conveniently!
// or leave it "AS IS" and use the following code to store them!
// remember that p and q are secret keys; and therefore,
// they need to be encrypted and stored in a secure medium
$data = [
"p" => $p,
"q" => $q,
"date" => date("d-m-Y H:i:s") /* displays: 2016-04-26 20:01:04 */
];
try
{
$stmt = $conn->prepare("INSERT INTO keytable (p, q, date)
VALUES (?, ?, ?) ");
/**
* $data contains three items: p, q, date.
* execute the place holder ? ? ?
*/
$stmt->execute($data);
}
catch (PDOException $e)
{
echo 'ERROR: Cannot insert data into the database: ' . $e->getMessage();
}
?>
There are lots of ways to test for prime. Google Miller-Rabin algorithm to test for primes as well.
PHP has a function called gmp_prob_prime() which uses Miller-Rabin algorithm to return primality test result.
Also note that using this form ++$i is 1/3 faster than $i++, which matters for big loops. So I recommend using this form: ++$i (the pre-arithmetic operator) for most of your programming code rather than the post-arithmetic operator: $i++.
<?php
/**
* Sieve of Eratosthenes method of finding primes
*
* php program to print all primes smaller than or equal to n
*
* $n = 2147483647
*/
public function sieveOfEratosthenes($n)
{
// create a boolean array "prime[0..n]"
// and initialize all entries as true.
// a value in prime[i] will finally be
// false if i is not a prime, else true.
$prime = array_fill(0, $n + 1, true);
for ($p = 2; $p * $p <= $n; $p++)
{
// if prime[p] is not changed,
// then it is a prime
if ($prime[$p] == true)
{
// update all multiples of p
for ($i = $p * $p; $i <= $n; $i += $p)
{
// if $prime[$i] is not a prime, return false
$prime[$i] = false;
}
}
}
// print all prime numbers
for ($p = 2; $p <= $n; $p++)
{
if ($prime[$p])
{
echo $p . " ";
}
}
} // end function sieveOfEratosthenes()
/**
* sieveOfEratosthenes() above can be called like this:
*
* $n = 50;
*
* sieveOfEratosthenes($n);
*
* output: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
*
* or if $n = 100;
*
* output: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
* 53 59 61 67 71 73 79 83 89 97
*/
?>
Create a function that will return an array containing a range of prime numbers. Because of the way in which the algorithm works, the function above isn't possible to generate just a selection of numbers, and as you can see from the output above, the numbers must all be generated and stored in the array variable $prime.
That is not very useful if you just want one prime number to use in your application and not the whole list of primes. The following function aims to achieve that goal.
<?php
/**
* find all the primes up to a given number using
* the Sieve of Eratosthenes algorithm.
*
* @param $start The number to start searching for prime numbers.
* @param $finish The number to stop searching for numbers.
*
* @return array The array of prime numbers.
*/
public function findPrimeRange($start, $finish)
{
// initialize the range of numbers.
$number = 2;
// create an array containing a range of elements from "2" to
// "2147483647":
// $range[2..2147483647]
// Array ( [2] => 2 [3] => 3 [4] => 4 [5] => 5 ...... )
$range = range(2, $finish);
// create an array by using the key elements from first argument as
// key and "value" from the second argument as value
// $prime[2] => 2, $prime[3] => 3, $prime[4] => 4, ....
$prime = array_combine($range, $range);
// loop through the numbers and
// remove the multiples from the primes array.
while ($number * $number < $finish)
{
for ($i = $number; $i <= $finish; $i += $number)
{
if ($i == $number)
{
continue;
}
unset($prime[$i]);
}
$number = next($prime);
}
// slice the array into the given range
foreach ($prime as $p)
{
if ($p < $start)
{
unset($prime[$p]);
}
else
{
break;
}
}
return $prime;
}
/**
*This can be used in the following way.
*
* print_r(findPrimeRange(30, 50));
* Array
* (
* [31] => 31
* [37] => 37
* [41] => 41
* [43] => 43
* [47] => 47
* )
*/
/**
* PHP code to check wether a number is prime or not
* function to check the number is prime or not
*/
public function primeCheck($number)
{
// we know that 0 and 1 are not primes!
if (($number == 0) || ($number == 1))
{
// not a prime
return 0;
}
// we know that 0 and 1 are not primes, so start with 2
for ($i = 2; $i <= sqrt($number); $i++)
{
if ($number % $i == 0)
{
return 0;
}
}
return 1;
}
/**
* Usage:
*
* $number = 31;
* $flag = primeCheck($number);
*
* if ($flag == 1)
* {
* echo "Prime";
* }
* else
* {
* echo "Not Prime"
* }
*/
?>
Check this out to find the next prime number say, if want to find the next prime number after 10, gmp_nextprime(10) will return 11. This PHP function is suiteable for looking for a certain prime number after a certain number, say, you want to find a prime number after 2436.
You could use PHP function gmp_nextprime() to your advantage to generate a list of prime numbers. For example:
<?php
/**
* mimicking a random prime number generator
*
* Usage:
* $prime = generatePrime(100);
*
* for() loop will loop through 100 times and generates 100 prime numbers
*/
public function generatePrime($n)
{
for ($i = 0; $i < $n; $i++)
{
// you can make the range as wide or narrow as you want!
// or as large or small as you want!
$j = rand(100, 200000);
// function gmp_nextprime() returns the next prime number after $j
$prime = gmp_nextprime($j);
try
{
// assuming $conn is a PDO object!
$stmt = $conn->prepare("INSERT INTO primetable (prime)
VALUES (?) ");
// execute the place holder ?
$stmt->execute($prime);
}
catch (PDOException $e)
{
echo 'ERROR: Cannot insert data into the database: ' . $e->getMessage();
}
} // end for()
} // end generatePrime()
?>
There you have it! A fast way to generate primes.
Here is more theories about generating primes.
Mathematicians for centuries have been trying to find equations for generating prime numbers, but their success has been slow and valid to only a small range of natural numbers.
Lenard Euler, the Swiss mathematician, came up with the following equation:
f(x) = x2 + x + 41, which is prime for x = 0, 1, 2, ..., 39.
This quadratic equation was the record holder for centuries as a consecutive, distinct quadratic prime-producer for an initial range of input values.
It is not, however, the current record holder. That distinction goes to this function:
f(x) = 36x2 - 810x + 2753, which is prime for x = 0, 1,..., 44.
As you have probably noticed, these functions are also very limiting in their range and are of very little or no practical use.
To be of any real use, we need a method that can produce an infinite number of primes, and of any size we want.
The best way found to deal with this problem, since there are no formulas for finding all prime numbers in sequence, is to instead find numbers that are "very likely" to be primes. Hence, testing for primes or primality.
If we are going to use our primes for industrial uses (e.g., encryption), we often do not need to prove that they are primes.
It may be enough to know that the probability they are composite is less than a given percentage (e.g., 0.000000000000000000000001). In this case, we can use (strong) probable primality tests.
Let's refresh our memory: A number that is not a prime is said to be a composite.
Most of these tests are based on what is known as Fermat's Little Theorem (named after a French mathematician named Pierre de Fermat (1601-1665)).
The Fermat's Little Theorem states:
If p is a prime and if a is any integer, then ap = a (mod p).
In particular, if p does not divides a, then a(p - 1) = 1.
You can't just pick a random number and use it as your RSA encryption key. It won't work. You have to test it for primality using Fermat's Little Theorem. You also can use PHP function gmp_prob_prime() which uses Miller-Rabin algorithm to return primality test result.
Basically, what Fermat's Little Theorem is trying to accomplish is to find the remainder of a number (a raise to the power of (p - 1)) by dividing a(p - 1) by p to equal 1.
That's what this equation a(p - 1) = 1 means.
And that's what the statement: "if p does not divides a, then a(p - 1) = 1" above means.
So p needs to be a prime number in order for it to be a remainder of 1.
Another way of saying is that, the left side divided by p equals to a remainder of 1. So you need to divide the left side by p until the remainder is equal to 1, then stop.
Please check out tutorials on YouTube on Fermat's Little Theorem
Let's see the proof of Fermat's Little Theorem.
Proposition:
If p is a prime and if a is any integer, then ap = a (mod p)
In particular, if p does not divide a, then a(p - 1) = 1.
Proof
Start by listing the first (p - 1) positive multiples of a
For a visual guide, see YouTube tutorials mentioned earlier.
For example:
a, 2a, 3a, .... (p - 1)a
Suppose that ra and sa are the same modulo p, then we have r = s (mod p),
so the (p - 1) multiples of a above are distinct and nonzero; that is,
they must be congruent to 1, 2, 3, ...., (p - 1) in some order.
Multiply all these congruences together and we find:
a.2a.3a .... (p - 1)a = 1.2.3 .... (p - 1) (mod p)
OR better:
a(p - 1) (p - 1)! = (p - 1)! (mod p)
Divide both sides by (p - 1)! to complete the proof.
Don't worry if you don't understand the proof! It's not important!
However, you need to know how to find the remainders of a number.
See YouTube tutorials mentioned earlier.
Conclusion: There is only one way to factorize a number into primes.
As you can see from the above proposition of the Fermat's Little Theorem, there is only one way to factorize a number into primes.
It's important to note that Fermat's Little Theorem is a compositeness test, and not a primality test; that is, it tells you for sure if a number is a composite (not a prime.)
If the test is positive, the number is guaranteed to be a composite, otherwise, it might be a prime.
However, statistically speaking, this method is good enough for many practical applications, including encryption--RSA in particular.
There are 1,091,987,405 primes less than 25,000,000,000; but only 21,853 pseudo-primes base two, which gives us an error probability less than 0.00009% (a very miniscule probability of error -- and we can live with that!).
Note that the term pseudo-prime refers to the result of the primality test to be a positive test (not necessarily that it is a prime. See the primality test above.
We can reduce this margin of error even further by using multiple bases. This is exactly what the Miller-Rabin method does. See next function illustration for the Miller-Rabin Primality Test below.
The Miller-Rabin primality test method gives us a proved probability of error less than 1/s2, where s is the number of bases we tried.
The following code illustration uses a built-in PHP function called gmp_prob_prime() to test the number for primality.
Behind the scene, function gmp_prob_prime() uses Miller-Rabin algorithm to return primality test result.
<?php
$max = 2147483647;
$primeFound = 0;
$probablePrime = 0;
for ($x = 1; $x <= $max; $x++)
{
$primeStatus = gmp_prob_prime($x);
if ($primeStatus == 1)
{
$probablePrime++;
}
else if ($primeStatus == 2)
{
$primeFound++;
}
}
echo "Total primes found between 1 and " . $max;
echo " - certain primes found: " . $primeFound;
echo "probable primes: " . $probablePrime;
?>
Based on that the following results were obtained:
Total primes found between 1 and $max - certain primes found:
1 - 100000 - certain primes found: 9592, probable primes: 0
Total primes found between 1 and $max is:
1 - 1000000 - certain primes found: 78498, probable primes: 0
Total primes found between 1 and $max is:
1 - 10000000 - certain primes found: 78498, probable primes: 586081
Total primes found between 1 and $max is:
1 - 100000000 - certain primes found: 78498, probable primes: 5682957
Total primes found between 1 and $max is:
1 - 1000000000 - certain primes found: 78498, probable primes: 50769036
Total primes found between 1 and $max is:
1 - 2147483647 - certain primes found: 78498, probable primes: 105019067
Don't worry if you don't understand the code above! It's not that important!
It's for illustration purpose only!
Instead, check out PHP documentation on gmp_prob_prime()
?>
Let's focus our attention in finding and factoring primes.
The dual problems of factoring integers and testing primality have surprisingly many applications for a problem long suspected of being only of mathematical interest.
As we'll see below, the security of the RSA public-key cryptograph system is based on the computational intractability of factoring large integers [i.e., (p - 1)(q - 1)].
Before we go on, I want to clarify one term that is being used throughout this tutorial and in other texts describing the RSA cryptography. That term is: factoring or factorize or plainly as factor.
What does it mean?
Well, in mathematics, to factor a number is to derive or break that number into small chunks so that the chunks still retain the original property or meaning.
For example, how many smaller chunks can 6 be broken into?
How many factors can 6 be factored?
Well, let's see the possibilities: 6/6 = 1, 6/1 = 6, 6/2 = 3, 6/3 = 2. Answer: 4 or 4 factors.
Notice that 6/4 = 1.5 and 6/5 = 1.2 are not factorizable.
You'll see later that we multiply two prime numbers (p - 1)(q - 1) to create a public key.
For example: (3 - 1)(5 - 1) = 8
Now 8 is the result of the factorization of (p - 1)(q - 1)
Note: 8 is not the factor of (p - 1)(q - 1). It is the result of factoring (p - 1)(q - 1)
.So that's what the term: factoring or factorize or factorization or plainly as factor means.
Now let's continue on from where we left off:
[A side note: As a more modest application, hash table performance typically improves when the table size is a prime number.
To get this benefit, an initialization function must identity a prime near the desired table size.]
As you imagine, factoring and primality testing are related problems. However, they are quite different algorithmically.
In the sections above, we saw that we can demonstrate that an integer is composite (i.e., not prime) without actually giving the factors.
To convince yourself of the plausibility of this, note that you can demonstrate the compositeness of any nontrivial integer whose last digit is 0, 2, 4, 5, 6, or 8 without doing the actual division.
The simplest solution to factorization is also the simplest one used in primality tests; that is, brute-force trial-division.
However, this is extremely slow for big numbers; and therefore, impractical for any real application.
Another solution, a bit faster than trial-division, is the Square Root Method. See an illustration later.
The Square Root Method is okay for small numbers (15 digits or less), but will become too slow for anything larger than that.
[Note: For heavy-duty industrial commercial encryption purposes, anything less than 150 digits is considered small.]
The Square Root Method as the name implies used square root to implement the function.
The fastest known algorithm used in factorization is the Number Field Sieve. It uses randomness to construct a system of congruences, the solution of which usually gives a factor of the integer.
The method was developed by Pollard and was used to factor the RSA-130 number (such a feat required enormous amounts of computation power.)
As you can see, the strength of encryption algorithms such as RSA relies on the fact that it's really hard to decompose a large number into its factors.
These algorithms use an integer n made of two or more primes, such as: n = p x q or n = p x q x r x s where p, q, r, and s are large prime numbers.
Breaking n into its factors requires an enormous amount of computation that can last for many years (even when using multiple machines).
To demonstrate how secure such algorithms can be, cash prizes were offered to those who manage to factorize these numbers.
This huge disparity between the ease of finding large prime numbers, and the difficulty of factoring large numbers, is fully exploited when devising secure forms of public key cipher systems.
In other words, finding large prime numbers is very easy, but factoring them is very hard.
The basic components of the system are two programs, an encryptor and a decryptor.
Both the sender/encryptor and receiver/decryptor need to have keys.
Typically, the keys will consist of one hundred or more digits -- a very large number. The security of the system depends on keeping some of the keys secret.
This method immediately raises the following question: How can we send the key to the receiver of our message?
If we decide to mail it through a postal mailing system, we need to trust that the mailing system is absolutely 100% secured and tampered proof. Can we trust that? If we send a food recipe to our family and relatives, there is no problem in sending the key through the mailing system.
Or we can always meet up with the person and hand the key to that person days, months, or years in advance and let that person use that key to send us encrypted materials whenever that person needs to do so.
Yeah, we can do that, but it's not very practical for other uses, say, when you want to send a sensitive document to a person far, far away in the other side of the world.
To solve this problem, Whitfield Diffie and Martin Hellman, in 1975, proposed the idea of a public key cryptosystem (PKS).
In a PKS, each potential message receiver A (which would be anyone who intends to use the system) uses a program that will produce not one, but two keys: An encryption key and a decryption key.
The encryption key is made public to all those interested in sending "the receiver" A a message, while the decryption key is kept secret.
Although the basic idea behind such a system is simple, designing it is not.
The one originally proposed by Diffie and Hellman turned out to be not as secure as they had thought, but a method devised a short time later by Rivest, Shamir, and Adleman (the RSA fame) proved to be much more robust and secure, and its byproduct, the RSA system, is now being used widely in international banking, online transactions, military and satellite communications, to name just a few.
The main difficulty for anyone designing such a system is that the encryption process should disguise the message to such an extent that it is impossible to decode it without the decryption key.
But because the essence of the system, and indeed of any cipher system, is that the authorized receiver can decrypt the encoded message, the two keys must be mathematically related.
The receiver's program and decryption key should exactly undo the effect of the sender's program and encryption key, so it should be theoretically possible to obtain the decryption key from the encryption key, provided one knows how the cipher programs work.
The trick is to ensure that, although it is theoretically possible to recover the decryption key from the publicly available encryption key, it is practically impossible.
Let's put it this way: To break the encryption, all you have to do is undoing or unraveling the public key that is publicly made available to anyone, including hackers. In other words, break the public key into its factors of p * q.
In mathematic, undoing the product of p * q means to do a multiplicative inverse of p * q.
So to break the public key, all you have to do is performing a multiplicative inverse of p * q.
This is how hackers break encryption by using computer programs to calculate the multiplicative inverse of the public key.
The public key = p * q
Or it is usually written as n = p * q.
To undo or break the public key, all you have to do is factoring the public key (or n) into its possible factors which is practically impossible if you use large prime numbers.
In the case of one-way ciphers such as RSA, the receiver's secret decryption key consists of two large prime numbers (p and q at least 75 digits each), and the public key consists of their product (a 150-digit number = 75 + 75).
With current technology, it's practically impossible to factor numbers of that size in a reasonable time.
In computer memory, each digit holds 16 bits. So when working with cryptography, you use numbers that are multiples of 16 or divisible by 16. For example, a 1024-bit and 2048-bit keys are divisible by 16.
In general, if you're working with numbers of size N bits, you'll need 2*N bits of storage. Each digit holds 16 bits. So, a 1024-bit key will need 1024 * 2 / 16 = 128 digits of storage.
Let's for the sake of simplicity, we use two primes: 2 and 3; and therefore, the public key becomes 6.
Now all we have to do to unravel the public key is to factor the public key, which is 6, into its original two primes: 2 and 3.
We can do it in our head with these small primes, and even with numbers reasonably large, hackers can still use computer programs to factor these public keys to unravel the public keys.
A computer can quickly compute the greatest common divisor of two numbers using the Euclidean algorithm, so an attacker can run the algorithm on two public keys. If their greatest common divisor is not 1, then the attacker has found a prime number dividing both keys, therefore breaking two keys at the same time.
For example, suppose two public keys were 239149 and 166381. It is difficult to factor either of these two numbers by hand, but the Euclidean algorithm can be done by hand, revealing that the two numbers have a greatest common divisor of 379.
To give you a quick idea of the importance of this algorithm, here are a few of the security protocols that currently implement RSA.
As I mentioned in the previous section, efforts to develop new algorithms to factorize such numbers are usually subjects for doctorate theses and can bring instant fame for those who succeed.
The current record for factorization is around 155 digits.
(Note: New algorithms designed for quantum computers, when and if they ever get to build one, may render this sort of encryption system obsolete, but until then, RSA will continue to be one of the safest encryption systems available.)
To create a good implementation of the RSA algorithm, you need three things:
A pseudo-random number generator to use to generate random primes.
It is generallly a typical practice to create primes using some random methods (i.e., rand()) to generate a random number and then test for prime, rather than just picking some numbers and test for primes. See earlier sections on how to generate primes, especially function findPrimeRange().
Also, be mindful of the "computationally intensive" problem when selecting a range of number to use in findPrimeRange().
Check this out as well to find the next prime number say, if want to find the next prime number after 10, gmp_nextprime(10) will return 11. This PHP function is suiteable for looking for a certain prime number after a certain number, say, you want to find a prime number after 25436.
More on this topic later.
With the facts presented up to this point, we can now start a formal description of the algorithm behind RSA.
The best way to describe it is using the simplest case possible: Where a sender, call it S, wants to send a message to a receiver, call it R.
For the particular case of this example, we will assume that the message is a two-digit integer. For example, 77.
Before it can receive secure messages from S or anyone else interested in sending messages, R will need to generate a public key.
To do this, R must find two large prime numbers, call them p and q, having at least 75 digits, then multiply them to make a number n such as n = p.q.
PHP has a function called bcmul() that multiplies two arbitrary precision numbers p and q. So n = bcmul(p, q).
n will be R's public key (and R should keep p and q a secret).
Somewhere in your coding process, you need to handle the keys gracefully, such as store them in a database or file or some secure medium, while at the same time, making sure that they can be easy access to them so that you can retrieve them quickly and use them.
If you choose to store them in a file, PHP has two functions to make storing/retrieving very easy. These functions are called file_put_contents() and file_get_contents().
// reading/retrieving keys from config file containing keys
$config = json_decode(file_get_contents('http://www.example.com/config/config.json'));
$key_expiration_date = $config['key']['KEY_EXPIRE'];
$login_expiration_date = $config['login']['LOGIN_EXPIRE'];
foreach ($config as $k => $v)
{
if ($k == 'key')
{
// test for certain expiration date and handle it accordingly
// you might find a more elegant way of comparing the two dates than this!
// you get the point!
if ($key_expiration_date > 'today's date')
{
// the expiration date has not been reached ... keys are still good!
// proceed on!
foreach ($v as $key => $value)
{
if ($key == 'P')
{
$p = $value;
}
elseif ($key == 'Q')
{
$q = $value;
}
elseif ($key == 'PUBLIC')
{
$public_key = $value;
}
elseif ($key == 'PRIVATE')
{
$secret_key = $value;
}
} // end inner foreach ($v as $key => $value)
} // end if ($key_expiration_date > 'today's date')
else
{
// keys have expired .... discard old keys and generate new keys!
// and update your json file to reflect your changes!
}
} // end if ($key == 'key')
elseif ($k == 'login')
{
// test for certain login expiration date and handle it accordingly
// you might find a more elegant way of comparing the two dates than this!
// you get the point!
if ($login_expiration_date > 'today's date')
{
// the login expiration date has not been reached ... keys are still good!
// handle login accordingly
}
else
{
// login keys have expired .... discard old keys and generate new keys!
// and update your json file to reflect your changes!
}
} // end elseif ($k == 'login')
} // end outer foreach ($config as $k => $v)
storing keys in the config file
this code below is incomplete due to space constraint.
please check out my other tutorial call "Introduction to Ajax" and navigate
to the very end of that tutorial to find example code similar to the one below.
$config = .......
file_put_contents('http://www.example.com/config/config.json',
json_encode($config, JSON_PRETTY_PRINT));
keys must be encrypted, especially the private key.
there are several pure PHP implementations of the symetry
algorithms on the Web that you can use to encrypt your keys,
such as RC4, AES, DES3, Blowfish, etc.
the process goes like this:
generate two primes and solve for d and then encrypt them and
store them.
when you need to use them, retrieve them and decrypt them and
use them.
there is a pure PHP implementation of the symetry algorithm
RC4 in my other tutorial called "Introduction to RC4."
now a json config.json file looks like this:
{
"key":
{
"P": "1e8f50c3a80b7c0",
"Q": "4a01fb7c0e92b6c",
"D": "0f0c1b3c0e5a218",
"E": "6a9e1f3c0e98b6c",
"PUBLIC": "e201ab3c39c7d4e1d",
"PRIVATE": "0f5b3c390g3d20b3c",
"KEY_EXPIRE": "2592000"
},
"login":
{
"USERNAME": "my_username",
"PASSWORD": "7ac1f1b7c0e92b6f",
"LOGIN_EXPIRE": "2592000"
}
}
note: do not embedd any comment in your json file!
basically, once you've retrieve this json file,
you can convert it into an array using json_decode() so that
you can iterate through your array as you normally would!
one last note:
it is a good idea to tie your keys to an expiration date,
so that you can discard them and issue new keys.
this practice adds extra security to your security system.
you can timestamp your key file and read the timestamp
of that file and compare it against the current timestamp.
for example, a value for a 24-hour timestamp is: 3600 * 24 * 30
or 2,592,000 miliseconds.
PHP's current timestamp function is: time()
$time is 24 hours old, it's 24 hours ago, it's yesterday!
$time = time() - (3600 * 24 * 30);
if your file time was created two days, filemtime() should
be less than $time. confusing?
check out PHP doc for filemtime()
filemtime() returns Unix timestamp in milliseconds: '20452718039105'
for example:
$filemtime = filemtime('http://www.example.com/config/config.json')
if ($filemtime < $time)
{
// expired
// do something!
}
how you implement such system is up to you!
the example shown here is not the only way to do it!
Besides the generation of the public key, R should agree with S on a method to encode the actual message text.
Now let's break the process of encrypting and decrypting the message into steps:
R needs to select two primes (see previous sections on finding primes, particularly function findPrimeRange()). Here, we'll use p = 17 and q = 31, for example.
Note that p and q must be kept secret.
But keep in mind that in real applications, this number must be at least 75 digits, depending on how secure you want your message to be.
As a rule of thumb, use a somewhat small number for your "not so important" message so that you don't consume too much processing power.
You increase the number accordingly as your message gets more sensitive.
That's why maintaining a storage device, i.e., file or database, for storing different levels of security is very crucial.
R now generates n by multiplying p and q. Such as n = 17 x 31; that is n = 527.
527 will be R's public key.
R now must calculate phi, which denoted by a Greek letter ϕ.
ϕ = (p - 1)(q - 1).
phi = (p - 1)(q - 1), which is 16 x 30 or 480.
R now chooses another number called it e which must meet these two conditions:
1. e must be between 1 and phi or 480.
2. e also must be a relative prime to phi or 480.
Remember the definition of relative prime?
To refresh your memory: A prime number is considered a relative prime to any other number if it (prime) does not divide that number. Another way of saying is that, choose a number e that is not divisible by the prime.
So e cannot divide 480. Or 480 is not divisible by e.
By the definition of relative prime, we know that the following numbers cannot divide 480: 7, 11, 13, 14, etc.
And 7, 11, 13, 14,.... must be between 1 and 480, so they all satisfy both conditions for step 4.
Notice that 14 is an even number and yet it does not divide 480. So it satisfies the definition.
Also notice that e doesn't need to be an odd number (as the even number 14 shows).
Now in real life (application) the hard part is finding e, especially if you're not math-inclined and especially when numbers must be very large as is the case when you program real RSA cryptography applications.
Basically, finding e comes down to finding a number e such as the Greatest Common Divisor (or GCD) between e and 480 is 1.
In other words, it's this equation: GCD(e, 480) = 1.
But not this equation: GCD(e, 480) = 0.
In practice, e is often chosen to be 216 + 1 = 655372, though it can be as small as 3 in some cases. In other words, do not choose e higher than 655372.
If your phi is larger than 655372, choose e between 3 and 655372 but no higher than 655372.
e will be the other half of the public key (and n is the other half).
Basically, the Greatest Common Divisor of two integers A and B is the largest integer that divides both A and B.
In other words, the Greatest Common Divisor of two integers e and 480 is the largest integer that divides both e and 480.
The Euclidean Algorithm is a technique for quickly finding the GCD of two integers.
PHP has a function to solve GCD. Check this out: Find the Greatest Common Divisor of two integers
Once you solve this equation: GCD(e, 480) = 1 using the Euclidean Algorithm to quickly find the GCD of two integers, then that is your number e for your step 4.
Please check out tutorials for the subject of Greatest Common Divisor on the Web, particularly on YouTube. It will make you a better RSA cryptosystem programmer.
Here are two of them:
The Extended Euclidean Algorithm to find the GCD of two integers The Extended Euclidean Algorithm to find the Modular Inverse of a number: How To Find The Inverse of a Number ( mod n ) - Inverses of Modular ArithmeticIn mathematic, an inverse of a number, n, is written as n-1 or 1/n.
Knowing that, we can use the Euclidean Algorithm to quickly solve the inverse of a number, say, 27, and then take a modulo of another number, say, 392.
Likewise, we can solve the inverse of a number, say, 11, and then take a modulo of another number, say, 480.
Later, I will show you how to calculate Euclidean Algorithm to find GCD(A, B) = 1.
For now let's forge on the rest of the description of the RSA algorithm.
If you look at the very beginning of this step 4, it says R needs to choose a number e. You can choose any number between 1 and 480 that does not divide 480 and it will work out just fine.
This is very easy using function findPrimeRange(1, 480) to list prime numbers between 1 and 480.
How you pick out a particular prime number from function findPrimeRange() is up to you.
However, it is very easy to do, for example, assuming prime holds the array of prime range generated by function findPrimeRange() [i.e., prime = findPrimeRange(1, 480)], you can easily pick out the array index: prime[3], prime[38], or prime[115], etc.
Let's do that now from the list: 7, 11, 13, 14, etc.
[Note: findPrimeRange() starts with prime[0] = 2, prime[1] = 3, prime[2] = 5, prime[3] = 7, prime[4] = 11]
Let's pick e = 11 for this example (or more specifically prime[4] = 11]).
The number e (11 in this case) is also part of the public key; and therefore, R will have to make it public together with n.
Make note: e and n are public keys. R can give both e and n to anyone that wants to send R messages.
So step 4 looks like this: GCD(11, 480) = 1
With the knowledge of n and e, the sender S can now prepare to send the message to R.
Let's call this message M.
It is necessary to convert the message M into a number because the RSA uses numbers to calculate the algorithm. One common conversion process uses the ASCII alphabet.
For this example, the message in our case is a single two-digit number. For example: M = 77. The ASCII code for M is 77.
It could be a file containing pages of texts, i.e.:
THE RED COATS ARE COMING! THE RED COATS ARE COMING! THE RED COATS ARE COMING!
....
T
= 84, H
= 72, E
= 69, a space
= 32, R
= 82, E
= 69, D
= 68, C
= 67, O
= 79, A
= 65, T
= 84, S
= 83, a space
= 32, A
= 65, R
= 82, E
= 69, a space
= 32, C
= 67, O
= 79, M
= 77, I
= 73, N
= 78, G
= 71, !
= 33.
For example, the message (M) THE RED COATS ARE COMING!
would be encoded as 847269328269686779658483326582693267797773787133
.
As you can see, that is an anormous large number. It is important that M < n, as otherwise the message will be lost when taken modulo n. In other words, the number 847269328269686779658483326582693267797773787133
raise to any power will be too computationally intensive and the computer will go haywire on you.
So if n is smaller than the message, as is often the case, it will be sent in pieces. In our example, n = 527, but our M is 77.
So it seems that we don't need to send the message character by character.
Now with n = 527 and M is 77, what else can we send? Not many characters. Try 'Me' = 7769
. That is over 527.
So no need to worry about M < n in this case. We'll send M as a single character.
Make note: If n is smaller than M, then S will have to send the message character by character (as our example M = 77 shows).
If you have a long string like THE RED COATS ARE COMING!
, send it one character at a time using our example (M = 77) as a guide.
Use loop(s) to loop through the encryption process, encrypting one character at a time.
Likewise, on the decryption side, use loop(s) to loop through the decryption process, decrypting one character at a time.
Later, as a bonus material, I probably will show you a secret of sending long strings like THE RED COATS ARE COMING!
broken into smaller pieces (if I have time) by using loops to convert ASCII characters to its ordinal number and back to its original ASCII character.
Other alternatives are to use one of the symetry encryptions like AES (Advanced Encryption Standard), DES (Data Encryption Standard), IDEA (International Data Encryption Algorithm), Blowfish (Drop-in replacement for DES or IDEA), RC4 (Rivest Cipher 4), RC5 (Rivest Cipher 5), RC6 (Rivest Cipher 6), etc.
I recommend using RC4 because it is fast and simple to use and millions of people, industries, and organizations have been using it for decades to send secure large documents. See my tutorial on RC4.
As for AES, DES, and IDEA are too overkilled for the majority of us who don't need military-grade encryption. Blowfish is also a little overkilled for the majority of our encryption tasks.
As for RC5 and RC6 are proprietary algorithms and you need to obtain permission from RSA Security to use them. That left us the RC4 as the best alternative to use.
So if you need military-grade encryption, use RSA encryption algorithm described in this tutorial, and for non-military-grade encryption, use RC4.
S now encrypts the message by appplying a sequence of mathematical operations over M that will result in the encrypted message C:
C = M e mod n, which for this example becomes:
C = 77 11 mod 527 or C = 8.
n and e are public keys.
Besides the public keys, the equation is the only information an attacker will be able to steal. Of course, you keep M as a secret, too.
To solve this equation, please check out tutorials on YouTube on Fermat's Little Theorem as well as on the subject of Greatest Common Divisor (on YouTube) listed below.
The following lists PHP's precision arithmetic functions that are suiteable for programming RSA encryption.
PHP has two functions for dealing with exponential and modulus -- the same sort of equation listed above. Please check these out:
bcpowmod() gmp_powm() to raise a number to a power with moduloIf your numbers are small enough not to cause memory overflow then using the two functions as well as other functions mentioned in this tutorial to calculate your RSA equations is fine. You have to decide of what level of security you're comfortable with your data and implement your RSA applications accordingly.
While you're at it, please check the following out as well. You probably will need to use a lot of these functions in your RSA algorithm code.
By the way, the function names listed below contain a "bc..." prefix, which stands for "basic calculator," because this precision arithmetic library extends from a GNU implementation utility interface created by Philip Nelson.
A simplier way of saying is that, the people at PHP created this precision arithmetic library by extending it from a GNU implementation utility interface created by Philip Nelson, and therefore, inheriting all of the functionalities from the parent interface.
See my other tutorial called "abstract verses interface" for more about how interfaces work.
Please note that Philip Nelson called it incorrectly as "basic calculator," but the people at PHP called it correctly as "binary calculator."
bcmod() mod() exp() pow() bcadd() bcsub() bcmul() bcdiv() bccomp() rand() array-rand() random_int()For more PHP mathematical functions check these out:
GMP Functions Mathematical Extensions Mathematical Extensions: Math_BigInteger PHP Secure Communications LibraryAs you can see from the functions above, all of these functions can handle large precision numbers, and you might be tempted to just calculate your RSA in raw fashion -- that is, calculate this equation
C = 77 11 mod 527 and this equation M = 8 131 mod 527 without breaking them down using
Euclidean Algorithm.
That will cause RAM memory problems.
If you watch the tutorials on YouTube mentioned above, particularly Fermat's Little Theorem, you will hear them say that a calculator is overwhelmed by the sheer large numbers that the equation C = 77 11 mod 527 or M = 8 131 mod 527 generates. It overflows the available memory.
So you can't use the functions listed above to solve all these equations in raw form because the equations contain exponential number that is typically too large for the RAM memory to handle and it is computationally too intensive. You have to break them down into small pieces using Euclidean Algorithm or some other means.
You can use the functions listed above for a reasonably medium size exponential numbers but not for larger exponential numbers, especially exponential larger than two digits such as 723 131 and 8 631. This one is probably okay: 723 11.
Remember that an RSA key that is more than 2500 bits is very very computationally expensive even just to generate it.
It's not the functions that cause the problems -- it's the computer's memory called RAM memory that is causing the problems.
Remember that the RAM memory is like a blackboard you find in schools for teachers to write on.
You know that a blackboard does not have a lot of spaces for a teacher to write on, so a teacher has to erase the chalk so that he/she can write new materials on. The RAM memory is the same thing. It has a limited space for programs to run on.
A calculator also uses RAM memory as its chip.
So take this warming seriously and break the equations into small pieces. Use the Euclidean Algorithm and Fermat's Little Theorem techniques to solve your equations.
Having said that, with a stern warning, you can still use the precision arithmetic functions listed earlier to calculate your RSA in raw fashion if your security level doesn't need to use large exponential numbers as long as you practice a sound encryption process.
In other words, you can still use a reasonably small number (or exponential number) according to your security level and still be secured as long as you practice a sound encryption process by encoding your encryption using bases, i.e., base16, base32, base64, base92, etc.
As a matter of fact, thousands and thousands of people, industries, organizations have been using these functions in raw fashion without having to break their equations into small pieces because they practice sound encryption process, such as encoding their encryption using bases, i.e., base16, base32, base64, base92, etc.
Please see my other tutorial called Introduction to Base64 Encryption.
You can also use sample codes from 'users contributed' section of the base_convert()
Encoding your RSA encryption adds extra security and makes it very very hard to break your RSA algorithm.
See bonus materials later where you break your strings into small pieces, and at the same time, encrypt those pieces twice: one with your RSA algorithm and after that, with the base encoding process to make it very very hard to break.
Not only that, you can also wrap your encryption using RC4 algorithm as well (on top of everything else) to make it even more hard to break -- making it a triple encoded firewalls. That is a very sound encryption process that you should always practice.
Now R, after receiving the encrypted message C, must decrypt it using the secret pair of prime numbers (p and q) used to create the public key.
R must first find the number d such that:
e.d mod (p - 1)(q - 1) = 1.
To compute the value for d, use the Extended Euclidean Algorithm to calculate d = e-1 mod phi, also can be written as d = 1/e mod phi.
This is known as modular inversion. Note that mod is not integer division. It's a remainder division.
The modular inverse d is defined as the integer value such that ed = 1 mod phi.
It only exists if e and phi have no common factors.
In other words, d only exists if e and phi have no common factors.
Basically (in our case), find d = (1/e) mod 480.
In our case, we can substitute the above equation (e.d mod (p - 1)(q - 1) = 1) with actual values:
11.d mod 480 = 1.
In other words, compute d = (1/e) mod 480.
Or it can be written in a formal mathematic notation like this: d = (1/e) mod 480 = 1.
But we're going to use this notation to compute d = (1/e) mod 480.
Now compute the right hand side for d.
We know the value of e = 11, so compute d = (1/11) mod 480 using the following tutorial on YouTube:
How To Find The Inverse of a Number ( mod n ) - Inverses of Modular Arithmetic.An inverse of a number 11 is written as 11-1 or 1/11
Or we can just pick d that satisfy this condition: d = (1/11) mod 480 = 1.
As you maybe well aware that there are several choices for d that will work out just fine for our equation.
Again, we can quickly find some suitable candidates for d, for example: d = 131 satisfies the condition.
The problem of finding d is equivalent to finding the modular inverse of a number.
Again, please check out tutorials for the subject of Modular Inverse of a number on the Web, particularly on YouTube. It will make you a better RSA cryptosystem programmer.
PHP has a function to solve Modular Inverse of a number. Check this out:
Find the modular inverse of a GMP number (GNU Multiple Precision : For large numbers)For example:
$inverse = gmp_invert("11", "480");
echo gmp_strval($inverse) . "\n";
While you're at it, check this out as well:
Find the modular inverse of a number: See 'Users Contributed' at the bottom of that page.Here is a function to compute the modular inverse of an integer using Extended Euclidean Algorithm that mimicks the PHP's gmp_invert() above:
<?php
// function to compute the modular inverse of an integer
public function Euclidean($a, $b)
{
// initializing players
$x = '1';
$y = '0';
$mod = $b;
do
{
// first, find the remainder of dividing a by b
$remainder = bcmod($a, $mod);
// next, find the quotient of dividing a by b
$q = bcdiv($a, $mod);
// now re-arranging the players
$a = $mod;
$mod = $remainder;
// now finishing up the calculation
$remainder = bcsub($x, bcmul($y, $q));
// now re-arranging the players again to be run through the loop again
$x = $y;
$y = $remainder;
}
while (bccomp($mod, '0')); // while (b == '0')
// test to see if b == '0'
// if it is, we're finished calculating, add b to x
// and then return x
if (bccomp($mod, '0') < 0)
{
$x = bcmadd($x, $b);
}
return $x;
} // end function Euclidean()
Usage:
$num = "64941057316178801556773346239351236811";
$mod = "2447995268898324993537772139997802321";
// verifying that ($num * $m) * Euclidean($num) is equal to $m
$m = "123456789";
$i = Euclidean($num, $mod);
// then test it out to see if the function works by
// verifying that ($num * $m) * Euclidean($num) is equal to $m
// you need to echo out this equation:
// echo bcmod(bcmul(bcmod(bcmul($num, $m), $mod), $i), $mod);
// if (bcmod(bcmul(bcmod(bcmul($num, $m), $mod), $i), $mod) == $m)
// if the left side equals to the right side, it works!
?>
Finally, to decode the message, R applies a sequence of mathematical operations on C as follows:
M = C d mod n, which for this example becomes:
M = 8 131 mod 527 or M = 77.
In other words, R translates M back into its original alphabet letter, retrieving the original message: M = 77.
Here is a video on YouTube on the subject of Modular Inverse of a number that explains it very well: How To Find The Inverse of a Number ( mod n ) - Using Fermat's Little Theorem.
As you can see, as long as R can keep the original two primes used to generate the public key a secret, he can be sure that messages addressed to him cannot be decoded and read or tampered with by anyone else.
So R needs to keep the original two primes a secret, but can give n and e to anyone that wants to send messages to him.
R can even give n and e to hackers just in case if hackers want to hack messages other people sent to R.
That's it!
Just follow these eight steps just outlined and you're on your way to programming applications very secure.
This concludes the formal RSA Algorithm tutorial. What you'd learned thus far will enable you the knowledge necessary to program very secure and powerful security applications. The sky is the limit! And don't forget to thank me later!
For the rest of the materials, they are just extra (bonus) materials to help you understand RSA algorithm further.
Recap:
Let's refresh our memory again about our eight steps.
Create two prime numbers called them p and q.
p and q must be kept a secret.
Find n = p * q.
Create a function called phi = (p - 1) * (q - 1).
Find e.
e must satisty two conditions:
1. 1 < e < phi
2. e must be a relative prime to phi.
The two conditions above can be easily handled using this function findPrimeRange().
For example, e = findPrimeRange(1, phi)
Prepare the message using either a character by character encoding or by other means.
Find d.
d must be kept a secret.
The basic formula used to encrypt a message M is this:
C = M e mod n
where M is the plain text message and C is the resulting encrypted message.
And e will be dependent on the two initial two primes (p and q) used to generate n.
e and n are public keys and can be given to anyone that wants to send messages.
The basic formula used to decrypt a message C is this:
M = C d mod n
where d will be dependent on the two initial two primes (p and q) used to generate n.
Again, d must be kept a secret.
As you can see from the two formulas for both encryption and decryption, the syntax for both is the same; and that is, a number M or C raise to the power (e or d) and then mod n. The only difference between the two formulas is the base number (M or C) and the raise power number (e or d).
This means that you can create only one function to calculate both encryption and decryption by passing to this function the appropriate values and the function should return the correct algorithm accordingly.
For example:
/**
* assuming $num is the number to be raised to the power $power
* and then modulo $mod, we can write the function for both
* encryption and decryption like this:
*/
public function rsa($num, $power, $mod)
{
// return the result of the calculation: M e mod n or C d mod n
// just remember to be mindful of the concept called
// "computationally intensive!"
}
/**
* Usage:
*
* $encrypt = rsa($encryption_number, $power_e, $mod_n);
*
* $decrypt = rsa($encrypt, $power_d, $mod_n);
*
* as you can see, you still call the same function, but with different values!
*/
By the way, the eight steps outlined above and the description described in this tutorial is not pertain to just PHP - it applies to other languages as well. You can implement RSA alogrithm described in this tutorial in other languages as well, such as Javascript, just to name one.
Later, I will provide Javascript precision arithmetic functions that mimick PHP's precision arithmeth functions listed earlier.
You can use most of them to do your own implementation of RSA alogrithm described in this tutorial.
Check out these videos on YouTube as well:
The RSA Encryption Algorithm (1 of 2: Computing an Example) The RSA Encryption Algorithm (2 of 2: Generating the Keys) The RSA Encryption Algorithm: Public Key Crypto with RSA)Now that you know an extensive detail about RSA Algorithm, you can use that knowledge to program very powerful and secure applications on your own.
However, as is always the case, there are lots of third-party tools out there that you can use to make your life easier. For example, to generate the public and private keys, you can use a tool called OpenSSL.
Please Google it.
See my other tutorial called Introduction to OpenSSL.
OpenSSL is a very popular tool that is widely being used all over the world. OpenSSL uses the RSA Algorithm that just outlined in this tutorial to generate both public and private keys and as well as certificates.
There are countless tools out there that use RSA Algorithm to make your life easier so that you don't have to do the hard math yourself. Check this out:
PHP Secure Communications LibraryFor your information: Nowaday, the RSA Algorithm is not the only algorithm available out there. There are plenty of algorithms out there available for your use. To list just a few, here they are: AES, DES, Blowfish, RC6 (an extension of Rc4), Rijndael, Serpent, MARS.
Please Google them.
Advanced Encryption StandardAdvanced Encryption Standard (AES) is a symmetric block cipher chosen by the U.S. government to protect classified information. AES is implemented in software and hardware throughout the world to encrypt sensitive data. It is essential for government computer security, cybersecurity and electronic data protection.
Symmetric, also known as secret key, ciphers use the same key for encrypting and decrypting, so the sender and the receiver must both know -- and use -- the same secret key.
The National Institute of Standards and Technology (NIST) started development of AES in 1997 when it announced the need for an alternative to the Data Encryption Standard (DES), which was starting to become vulnerable to brute-force attacks.
Blowfish is an encryption technique designed by Bruce Schneier in 1993 as an alternative to DES Encryption Technique. It is significantly faster than DES and provides a good encryption rate with no effective cryptanalysis technique found to date. It is one of the first, secure block cyphers not subject to any patents and hence freely available for anyone to use.
RC6 is a derivative of RC5 (and RC5 is a derivative of RC4) and is a block cipher designed for RSA Security. RC6 uses four working block size registers in its algorithmic computations, whereas RC5 uses only two. Thus, RC6 is faster. RC6 was designed as part of the Advanced Encryption Standard (AES) competition, where it was a finalist. It is a propriety algorithm patented by RSA Security.
So to use the RC5 or RC6, you have to obtain a permission for their uses. However, the RC4 is not patented and is freely available for anyone to use.
Rijndael (pronounced rain-dahl) is the algorithm that has been selected by the U.S. National Institute of Standards.
Rijndael is a symmetric key encryption algorithm that's constructed as a block cipher. It supports key sizes of 128, 192 and 256 bits, with data handling taking place in 128-bit blocks. In addition, the block sizes can mirror those of their respective keys.
The Rijndael Block Cipher - NIST Computer SecurityAs stated earlier, to create a good implementation of the RSA algorithm, you need three things, which were listed earlier.
One of the three things is that, you need to do a precision arithmetic (actually multiple precision arithmetics).
Feel free to skip this RSA Algorithm Arithmetic section and jump to the RSA Algorithm Implementation section ahead to see the actual implementation of the RSA algorithm using what w've learned thus far, plus using the upcoming RSA algorithm arithmetic as well.
Okay, let's touch bases on some of the arithmetics involved in the RSA algorithm using precision arithmetics.
As you may already know, the PHP functions listed above is enough for calculating precision RSA Algorithm Arithmetic. But sometimes, you need Javascript precision arithmetics as well. The following are Javascript functions that mimic the behaviors of PHP precision arithmetic functions listed above.
/**
* initilize cryptography functions of the specified bits
*
* function initcrypt(bit)
* {
* if (bit != 0)
* {
* setTimeout(('sendinit(' + bit + ')'), 200);
* }
* }
*
* returns a to the power of b mod c
*
* Ah.... this function needs a refinement!
*
* Usage:
*
* function sendinit(bit)
* {
* rc4key = rand(0, 9) + rand(0, 9) + rand(0, 9) + rand(0, 9) +
* rand(0, 9) + rand(0, 9) + rand(0, 9) + rand(0, 9);
*
* while (rc4key.length + 8 <= RSAmodulok.length - 3)
* {
* rc4key += (rand(0, 9) + rand(0, 9) + rand(0, 9) + rand(0, 9) +
* rand(0, 9) + rand(0, 9) + rand(0, 9) + rand(0, 9));
* }
*
* ibPowmodInPart(rc4key, RSApublick, RSAmodulok, '1', 0);
* }
*
*/
function ibPowmodInPart(a, b, c, r, i)
{
// RSA encryption is broken up into parts
// because it is computationally expensive
r = ibmod(ibmul(r, a), c);
i++;
if ( i < parseInt(b))
{
var h = 'ibPowmodInPart("' + a + '", "' + b + '", "' +
c + '", "' + r + '", "' + i + '")';
setTimeout(h, 500);
}
else
{
return r; // returns the results to caller
}
}
// Integer Binary Math library
// returns 0 on equel, 1 on a > b, -1 on a < b
// in other words, it returns true if a > b
function ibgreater(a, b)
{
a = a + '';
b = b + '';
if (a.length > b.length)
{
return 1;
}
if (a.length < b.length)
{
return -1;
}
var i = 0;
while (a.charAt(i) == b.charAt(i) && i < a.length)
{
i++;
}
if (i == a.length)
{
return 0;
}
if (a.charAt( i) > b.charAt(i))
{
return 1;
}
else
{
return -1;
}
}
// returns a + b
function ibadd( a, b)
{
a = a + '';
b = b + '';
var l = a.length;
while (b.length < l)
{
b = '0' + b;
}
if (b.length > l)
{
l = b.length;
}
while (a.length < l)
{
a = '0' + a;
}
l--;
var c = 0;
var r = '';
for (var i = l; i > = 0; i--)
{
c = c + parseInt(a.charAt(i)) + parseInt(b.charAt(i));
if (c > 9)
{
c = c - 10;
r = '' + c + r;
c = 1;
}
else
{
r = '' + c + r;
c = 0;
}
}
if (c == 1)
{
r = '' + c + r;
}
while (r.charAt(0) == '0' && r.length > 1)
{
r = r.substring(1);
}
return r;
}
function ibsub(a, b)
{
// returns a - b or NV9999. . . if b > a
a = a + '';
b = b + '';
var r = '';
var l = a.length;
while (b.length < l)
{
b = '0' + b;
}
if (b.length > l)
{
l = b.length;
}
while (a.length < l)
{
a = '0' + a;
}
l--;
var c = 0;
var r = '';
for (var i = l; i >= 0; i--)
{
c = parseInt(a.charAt(i)) - parseInt(b.charAt(i)) - c;
if (c < 0)
{
c = c + 10;
r = c + r;
c = 1;
}
else
{
r = c + r;
c = 0;
}
}
while (r.charAt(0) == '0' && r.length > 1)
{
r = r.substring(1);
}
if (c == 1)
{
r = 'NV' + r;
}
return r;
}
// returns a * b
function ibmul(a, b)
{
a = a + '';
b = b + '';
var v = [a];
var vr = [1];
var i = 0;
while (ibgreater(b, vr[i]) != -1)
{
v[i + 1] = ibadd( v[i], v[i]);
vr[i + 1]= ibadd( vr[i], vr[i]);
i++;
}
var r = '0';
var d = b;
for (var i = v.length - 1; i >= 0; i--)
{
if (ibsgreater(d, vr[i]) != -1)
{
r = ibadd(r, v[i]);
d = ibsub(d, vr[i]);
}
}
return r;
}
// returns a / b
function ibdiv(a, b)
{
a = a + '';
b = b + '';
if (ibgreater(b, '0') == 0)
{
return 'NV';
}
if (ibgreater(a, b) == -1)
{
return '0';
}
if ( ibgreater(a, ibadd(b, b)) == -1)
{
return '1';
}
var r = 0;
var d = a;
var v = [b];
var vr = [1];
var i = 0;
var t = '';
while (ibgreater(d, v[i]) == 1)
{
v[i + 1] = ibadd(v[i], v[i]);
vr[i + 1] = ibadd(vr[i], vr[i]);
i++;
}
for (var i = v.length - 1; i >= 0; i--)
{
if (ibgreater(d, v[i]) != -1)
{
d = ibsub(d, v[i]);
r = ibadd(r, vr[i]);
}
}
return r;
}
// returns a mod b
function ibmod(a, b)
{
//return ibsub(a, ibmul(b, ibdiv(a, b)));
a = a + '';
b = b + '';
if (ibgreater(b, '0') == 0)
{
return 'NV';
}
if (ibgreater(a, b) == -1)
{
return a;
}
var r = 0;
var d = a;
var v = [b];
var vr = [1];
var i = 0;
var t = '';
while (ibgreater(d, v[i]) == 1)
{
v[i + 1] = ibadd(v[i], v[i]);
vr[i + 1] = ibadd(vr[i], vr[i]);
i++;
}
for ( var i = v.length - 1; i >= 0; i--)
{
if (ibgreater(d, v[i]) != -1)
{
d = ibsub(d, v[i]);
r = ibadd(r, vr[i]);
}
}
return d;
}
// raise a to power b
function ibpow(a, b)
{
a = a + '';
b = b + '';
var v = [a];
var vr = [1];
var i = 0;
while (ibgreater(b, vr[i]) != -1)
{
v[i + 1] = ibmul(v[i], v[i]);
vr[i + 1] = ibadd(vr[i], vr[i]);
i++;
}
var r = '1';
var d = b;
for (var i = v.length - 1; i >= 0; i--)
{
if (ibgreater(d, vr[i]) != -1)
{
r = ibbmul(r, v[i]);
d = ibsub(d, vr[i]);
}
}
return r;
}
// small power mod
function ibpowmod(a, b, c)
{
a = a + '';
b = b + '';
c = c + '';
var r = '1';
for (var i = 0; i < parseInt(b); i++)
{
r = ibmod(ibmul(r, a), c);
}
return r;
}
Here are two Javascript functions to find the GCD
of two integers a and b:
This one uses while loop to achieve the result:
function gcd(a, b)
{
var r;
while ((a % b) > 0)
{
r = a % b;
a = b;
b = r;
}
return b;
}
This one uses recursive calls to achieve the result:
function gcd(a, b)
{
if (b == 0)
{
return a;
}
else
{
return gcd(b, (a % b));
}
}
Next up is the Greatest Common Divisor.
Okay, let's go over the Greatest Common Divisor involved in the RSA algorithm.
Warning This tutorial is very confusing and complex. So please use tutorials on YouTube instead.
The Euclidean Algorithm for finding GCD(A, B) is as follows:
The above illustration can be written in code like this:
<?php
// if everything divides 0
if ($a == 0 || $b == 0)
{
return 0;
}
?>
Example:
Find the GCD of 270 and 192
Or as an equation: GCD(270, 192) = 1
Another way of illustration for the above case can be written in code like this:
<?php
function Euclidean($a, $b)
{
// you know from basic math: any number divides 0 is 0
if ($a == 0 || $b == 0)
{
return 0;
}
}
?>
Again, we can write it as an equation: GCD(192, 78) = 1
And we can continue on until GCD(192, 78) = 0, as you can see from the following pattern.
A = 192, B = 78
A = 78, B = 36
A = 36, B = 6
A = 6, B = 0
So we have shown that:
GCD(270, 192) = GCD(192, 78) = GCD(78, 36) = GCD(36, 6) = GCD(6, 0) = 6
So we found the final answer to be: 6.
Or more specifically:
GCD(270, 192) = 6
That's it!
If we examine the Euclidean Algorithm we can see that it makes use of the following properties: