tag:blogger.com,1999:blog-282152922024-03-18T03:59:26.235+01:00DragonBe's PHP blogBlogging about PHP and related technologiesM. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.comBlogger240125tag:blogger.com,1999:blog-28215292.post-25404697751486366442019-03-25T10:00:00.000+01:002019-03-25T10:00:16.291+01:00Practical example: building a social sharing platformDocumenting your project upfront requires time and research, but gives enormous amount of insights and knowledge for the whole team to advance with.<br />
<br />
In this article we're continuing where we left off my previous article "<a href="https://www.dragonbe.com/2019/02/documentation-of-project.html" rel="nofollow" target="_blank">Documentation of a project</a>" by providing examples for the documentation focus areas I explained and we're also making sure that we're not tumbling down a rabbit hole where specs are written in stone and we're building this project in a waterfall way.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2uwonW5AtQXt5pbdj6qMS4G6sL-7njX-9en5FhP73dMT_vDwbfcl-4Ca943lBSZsLIJki5uQxeBgj3MIuz53nUzYiAXSv91UEsoSQ8xP8ql-Y4fYXth0KA5z8I16GbRKvVfVrKg/s1600/Hotbrewd_promo.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2uwonW5AtQXt5pbdj6qMS4G6sL-7njX-9en5FhP73dMT_vDwbfcl-4Ca943lBSZsLIJki5uQxeBgj3MIuz53nUzYiAXSv91UEsoSQ8xP8ql-Y4fYXth0KA5z8I16GbRKvVfVrKg/s640/Hotbrewd_promo.png" width="640" /></a></div>
<h2>
The Hotbrewd project</h2>
For this particular example I've chosen a project that has a couple of interesting challenges. It's a social media platform (lots of users) where people can check in their beverage at a specific location or establishment (geolocation), upload photos or videos of their drink (moderation) and share with friends (personal information, profiling). To make it a little entertaining, the more people share and tag, the more stickers they can unlock. Also brands and establishments can offer discounts for specials (marketing, monetisation).<br />
<h3>
The project feature requirements</h3>
Together with the business we define <b>feature requirements</b>. This is a list of requirements made from a business perspective. We need this list to ensure that we can build something the business wants and should contain verifiable criteria. In the case of Hotbrewd, the feature requirements are written out in a specification document. This can be a Word file, a Google document or as we like to use at <a href="https://www.in2it.be/" rel="nofollow" target="_blank">In2it</a> a wiki entry.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgj1DWt3-_XJN8BW19iKtF-xUSMBr1GcXCYMJdXrMF_oCG4LZLtVOB6vtngec_ey23uEUwIEFK5YgsHg9sR52Dp-uePgt4w1M4qkcAIhMv6Hm-Pt_VG6au-cr_i1lLR3izP4Yr3RA/s1600/Hotbrewd+Requirements.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="823" data-original-width="1600" height="328" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgj1DWt3-_XJN8BW19iKtF-xUSMBr1GcXCYMJdXrMF_oCG4LZLtVOB6vtngec_ey23uEUwIEFK5YgsHg9sR52Dp-uePgt4w1M4qkcAIhMv6Hm-Pt_VG6au-cr_i1lLR3izP4Yr3RA/s640/Hotbrewd+Requirements.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">A wiki entry providing feature requirements</td></tr>
</tbody></table>
<h3>
Defining technical requirements</h3>
Now that we know what the business wants, we can start defining the technical requirements. This sounds easier than it is because at this stage we only have a vague idea what kind of application we're going to build and how the technical infrastructure would look like. But we have no clue how many users will be on this platform, where constraints could be in the network or services or what kind of data is collected that needs protection.<br />
<br />
To answer these questions, we are going to interview the developers, system administrators and business owners to note down their views, experiences and expectations. We are focussing closely on how they envision the application. Sketching out their visions helps to find commonalities amongst all stakeholders and to draft up a technical architecture schema.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6SfNpHPhyphenhyphengU5FzKw_ik9Ps5dSXpJocjqNRZX6CShWdbGGWWg_qgMqK8sfo-DRQDt7NEf5ZfFZAlUTF3RZ0kz1X5M8OUt_0rqKLia8m10ZaBoQmV1eKKTSkunhIVJERLLL1XDyIg/s1600/Hotbrewd+application+architecture.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="999" data-original-width="1404" height="454" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6SfNpHPhyphenhyphengU5FzKw_ik9Ps5dSXpJocjqNRZX6CShWdbGGWWg_qgMqK8sfo-DRQDt7NEf5ZfFZAlUTF3RZ0kz1X5M8OUt_0rqKLia8m10ZaBoQmV1eKKTSkunhIVJERLLL1XDyIg/s640/Hotbrewd+application+architecture.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Quickly after interviewing all stakeholders you can form an idea how the application architecture would look like</td></tr>
</tbody></table>
<h3>
Security considerations</h3>
Now is a good time to define some security considerations! The business wants to build an application for the masses, but doesn't want to be in the news because sensitive data got stolen or the application got abused. With the help from security experts we can define areas of concern that everyone should be aware of. These areas are:<br />
<br />
<ul>
<li>Network security</li>
<li>Systems security</li>
<li>Application security</li>
<li>Application abuse</li>
</ul>
<div>
<b>Network security</b> is required to ensure that only the application can access the underlying systems and only has a single entry point (the reverse proxy).</div>
<div>
<br /></div>
<div>
<b>Systems security</b> is oriented towards the operating system (OS) and its libraries or tools that are installed on the platform.</div>
<div>
<br /></div>
<div>
<b>Application security</b> focusses on ensuring that all components of the application are protected agains malicious attacks. Primary area of concern is the <a href="https://www.owasp.org/index.php/Category:OWASP_Top_Ten_2017_Project" rel="nofollow" target="_blank">OWASP Top 10</a>, a list of 10 most common attack vectors seen in web applications. But just as important are measures taken to ensure the application components can communicate safely and securely.</div>
<div>
<br /></div>
<div>
<b>Application abuse</b> is a risk based analysis of how the application could and would be abused, beyond the scope of the vision of the business. A potential abuse element is the fact people can upload photos and videos. The business would like users to upload shots of their coffees, but nothing prevents them to upload violent or provocative material. Another point of abuse could be stalking, because the application collects information where a beverage is consummated. And when you look at the whole application you come up with a very, scary list of all things that could be abused using the application as designed.</div>
<h3>
Working towards a POC</h3>
<div>
With all knowledge gathered, it's a good idea that you work to a first proof of concept (POC). This doesn't require a complete architecture or full infrastructure, but gives everyone a good idea how all things communicate together. And the business has something they can already start playing with the idea and work out how to improve the user experience.</div>
<div>
<br /></div>
<div>
Don't forget to keep meeting notes and add it to the documentation stack!</div>
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfEXnlC9-XwNKAhNdLuunxgBsQKT0SpYJXW5xsXY4m5gAwYnDsqm63b_Qtc_1gHOi-oqI8JsUWTzF2zEKjyVDIw0suzebrhm8y-b3DGwaY6TAdml1GdQY9MOAxuGJrPOpCfPhSkg/s1600/Hotbrewd+poc.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="569" data-original-width="960" height="378" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfEXnlC9-XwNKAhNdLuunxgBsQKT0SpYJXW5xsXY4m5gAwYnDsqm63b_Qtc_1gHOi-oqI8JsUWTzF2zEKjyVDIw0suzebrhm8y-b3DGwaY6TAdml1GdQY9MOAxuGJrPOpCfPhSkg/s640/Hotbrewd+poc.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">A first POC, doesn't have to be fancy but should contain the basic requirements</td></tr>
</tbody></table>
<div>
<br /></div>
<div>
Your project backlog can now be filled with development tasks, security tasks, design tasks, testing tasks and so on. A simple <a href="https://en.wikipedia.org/wiki/Kanban_board" rel="nofollow" target="_blank">Kanban board</a> can really help out as it makes work visible in the organisation.</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLwVp9aVJoZrsddeNTiAQpIYyU1jPSgxVG-YbuMjQVsg11A58S446S2I1fSAA5s87O8cPC1-dmONtI3ODNaON-qoehpuym2uCyl5x-yYcxSPOp_T5QDlWnHhetjkMK097_g9H6yQ/s1600/Hotbrewd+workboard.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="823" data-original-width="1600" height="328" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLwVp9aVJoZrsddeNTiAQpIYyU1jPSgxVG-YbuMjQVsg11A58S446S2I1fSAA5s87O8cPC1-dmONtI3ODNaON-qoehpuym2uCyl5x-yYcxSPOp_T5QDlWnHhetjkMK097_g9H6yQ/s640/Hotbrewd+workboard.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">A simple Kanban board to make work visible</td></tr>
</tbody></table>
Now that we have work in the pipeline, an idea on paper and an application to protect, I'm going to take some time to write out all the security related issues I come across and I will put them in writing in my next article. Please keep sending your feedback, suggestions and comments as it helps me get better insights in web application security. See you all next time.<br /><div>
<br /></div>
M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com0tag:blogger.com,1999:blog-28215292.post-88418007858265684042019-02-20T10:00:00.000+01:002019-02-20T10:00:02.532+01:00Documentation of a projectIn my <a href="https://www.dragonbe.com/2019/02/getting-to-understand-basics-of-security.html">previous post</a> I described 10 steps we should take to improve security of web applications. In this article I'm going to describe the purpose of documenting a project and what information should be included.<br />
<blockquote class="tr_bq">
Every successful project requires documentation to communicate a project goal and requirements to reach it.</blockquote>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQONNe5LNOmSeDPyeKjYaGmLnftkN4pjXnTXNFtvqsBwvstXlv-jGZB7Ud8zJn4AfK_ceXPYxOXDmJGoFh_qjAhJocOW0DiM2n12Co1SGxSH7Q72x5aeI0eXuBa6ZDz04buWLMig/s1600/documentation.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="460" data-original-width="650" height="452" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQONNe5LNOmSeDPyeKjYaGmLnftkN4pjXnTXNFtvqsBwvstXlv-jGZB7Ud8zJn4AfK_ceXPYxOXDmJGoFh_qjAhJocOW0DiM2n12Co1SGxSH7Q72x5aeI0eXuBa6ZDz04buWLMig/s640/documentation.jpg" width="640" /></a></div>
<h2>
Purpose of documentation</h2>
The reason documentation exists is to communicate in a clear, understandable language with all people involved. For web applications this documentation should describe the idea as a concept, steps needed to convert the idea into an application, what tools, applications and services are required in the proces of building the application, how the application is architected and who are the people involved.<br />
<br />
Since documentation is never complete, a good structure is required to allow additions or corrections being made over time. I prefer to use a <a href="https://en.wikipedia.org/wiki/Wiki">Wiki</a> type of platform to write my documentation. A wiki has often a simplified markup language and allows for multiple editors to collaborate on the documentation. <a href="https://www.wikipedia.org/">Wikipedia</a> is a great example of using a wiki to write documentation. But other tools are equally good like Google Docs, Microsoft Sharepoint or Microsoft Word documents on a shared drive in your organisation.<br />
<br />
For all our project we are using <a href="https://phacility.com/phabricator/">Phabricator</a> as we can integrate references to tasks, commits, users and a whole lot more features in our documentation wiki, making it a true source of reference. With Phabricator we're able to create global knowledge in our team and in our whole organisation.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjolIkUyS7VayFKoWzUxbmvpwBn5gI3DgNxOnZZa737Y5Zcov8qGx-29MhOcfmUJTRYv_UxDcJRqpmKHtdJOYZNfEVxIl2-I5xTSNUtA_yQS3wcWFdFQe8g_cINgffv1R6_t_lgaw/s1600/phabricator_example.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="Example screens of Phabricator" border="0" data-original-height="620" data-original-width="1600" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjolIkUyS7VayFKoWzUxbmvpwBn5gI3DgNxOnZZa737Y5Zcov8qGx-29MhOcfmUJTRYv_UxDcJRqpmKHtdJOYZNfEVxIl2-I5xTSNUtA_yQS3wcWFdFQe8g_cINgffv1R6_t_lgaw/s640/phabricator_example.png" title="Example screens of Phabricator" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Example screens of Phabricator</td></tr>
</tbody></table>
<br />
<h2>
Structuring documentation</h2>
As mentioned earlier, documentation changes over time for a lot of reasons. Here are a few common reasons why I needed to change or add documentation:<br />
<ul>
<li>Ideas change over time</li>
<li>Team members come and go</li>
<li>Unforeseen problems have surfaced</li>
<li>More features are requested</li>
<li>Unexpected events occured</li>
<li>Hardware requirements changed</li>
<li>Regulation, compliance or company structure changed</li>
<li>...</li>
</ul>
To prepare your documentation for these and other changes, a documentation structure is required. What works for me and the people I work with is a structure based on "expanding knowledge". This is a structure that allows your documentation to grow, without becoming a single massive document.<br />
<ul>
<li><b>project name:</b> just a name you give your project<ul>
<li><b>base:</b> this is the front-cover of the project containing just a brief description of the idea and goal of the project. It also serves as the base for your documentation hierarchy.<ul>
<li><b>project:</b> This is a container location where you can create documentation describing the project phases or goals like "Initial phase", "MVP", "Alpha release", "RC4", etc…</li>
<li><b>architecture:</b> This is also a container location where we describe all the requirements needed to run our application, segmented into specific environments like development, testing, staging and production. We even provide a segment to describe our CI/CD. Examples are hardware details, cloud services, applications like PHP, MySQL and Nginx. But also network, certificates and optionally what type of secrets are required to access and interact with our systems (not the actual certificates and secrets)</li>
<li><b>meeting notes:</b> I like to keep meeting notes part of a project because it helps explain why certain choices were made and gives full transparency to the team</li>
</ul>
</li>
</ul>
</li>
</ul>
At the start of every project I'm also using Phabricator's feature to create a "space", "team", "project" and "tag". Let me first explain what they mean.<br />
<ul>
<li><b>project:</b> identifies the main project and can have sub-projects</li>
<li><b>team:</b> allows me to select members of a team, often given the name of the project like "Acme Website Team" or "Corp CRM Refactoring Team" which I can assign on a project or sub-project.</li>
<li><b>space:</b> this is a restricted area that I can assign on a project and give permissions to the project team members to access the information kept within the space</li>
<li><b>tag:</b> I use tags just to label certain aspects in the lifecycle of a project. Tags are common across multiple projects like "meeting", "infrastructure", "easy pick", etc… and allow users to find information more quickly</li>
</ul>
The combination of spaces, teams, projects and tags with the documentation architecture described above gives me and the teams I work with clarity and insights about what needs to be done and what goals are to be reached.<br />
<h2>
Security aspect</h2>
As you're defining the components needed to work on your web application, don't forget to include security in your documentation! Most projects I worked on have been approached from a functional perspective where features and functionality are well documented, the architecture defined in terms of hardware and software requirements and who's doing what.<br />
<br />
What I define as "security" documentation can be listed as the following:<br />
<ul>
<li><strong>servers:</strong> the physical, virtual or container bases systems where (parts of) your project resides on, files are kept and data is persisted</li>
<li><strong>network:</strong> the physical or virtual connection between all the components, sockets included</li>
<li><strong>protocol:</strong> the way components of your application are communicating with each other</li>
<li><strong>direction:</strong> the direction communication goes, sometimes one way, sometimes both ways</li>
<li><strong>ports:</strong> which ports are required to communicate over? Even though this can be considered part of <em>Network</em> documentation, I consider it important enough to give it a specific mentioning</li>
<li><strong>operating system:</strong> the choice of operating system is important for the purpose of the application and defines the tools to be used to install the required services on it</li>
<li><strong>services:</strong> each component of your application requires a separate service and it's a good practice to define them in advance, including the technology stack in which you build your web application</li>
<li><strong>secrets and certificates:</strong> define upfront what type of certificates you need and how secrets are managed so you have a procedure ready when you need to apply it (I like to use <a href="https://www.vaultproject.io/">HashiCorp Vault</a> for management of these "secrets")</li>
</ul>
<h2>
Automation is key</h2>
Setting up environments with all required bells and whistles is a repetitive task that should be automated. It allows you to set up systems faster, but allows you to make improvements over time. This results in more stable and better protected systems. It also removes the fear that a step is skipped or a configuration setting forgotten.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL1d2XpKHaTKUbyf1JB-KFD2bzpSlm1UeuWJOXjyKhXtSYdrnTrhKouzrv5Dsq_D17RtUHLsQBd5VnAIiiRuqZcitQ2-Px0babN_Hb1aSgQPLkFqbFRmOkok2dUKDojfRwhV7urA/s1600/automation_tools.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="Automation Tools" border="0" data-original-height="664" data-original-width="1161" height="366" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL1d2XpKHaTKUbyf1JB-KFD2bzpSlm1UeuWJOXjyKhXtSYdrnTrhKouzrv5Dsq_D17RtUHLsQBd5VnAIiiRuqZcitQ2-Px0babN_Hb1aSgQPLkFqbFRmOkok2dUKDojfRwhV7urA/s640/automation_tools.png" title="Automation Tools" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Automation tools to configure and provision infrastructure as code</td></tr>
</tbody></table>
<br />
<h3>
GIT SCM</h3>
<a href="https://www.git-scm.com/">GIT</a> is not an automation tool but is an essential part of the automation process. GIT is a version control system where mostly developers keep their application code. But because GIT can be used for all text based (and limited binary) tracking of changes, we can also use it to store the automation artefacts in it.<br />
<h3>
CI/CD</h3>
A continuous integration (CI) and continuous deployment (CD) platform is not essential but highly recommended for the purpose of automation. My personal favourite is <a href="https://www.jenkins-ci.org/">Jenkins CI</a>, but there are many alternatives you can install on-prem or are being provided as a SaaS. Just search for "CI/CD Tool" in a search engine of choice you'll find plenty of solutions. NOTE: All automation tools mentioned below can also be triggered by manual commands on the command line.<br />
<h3>
Terraform</h3>
<a href="https://www.terraform.io/">HashCorp Terraform</a> is a great tool to treat infrastructure as code. It allows you to quickly create your VM instances by using blueprints. Especially for <a href="https://aws.amazon.com/">Amazon Web Services</a>, <a href="https://www.azure.com/">Azure</a> or <a href="https://cloud.google.com/">Google Cloud Platform</a> cloud services it works really well. If you're using <a href="https://www.vmware.com/">VMWare vSphere</a> or <a href="https://www.docker.com/">Docker Containers</a>, Terraform can be a true help. A full list of supported infrastructure can be found at <a href="https://www.terraform.io/docs/providers/index.html">www.terraform.io/docs/providers/index.html</a>.<br />
<h3>
Ansible</h3>
<a href="https://www.ansible.com/">RedHat Ansible</a> is a provisioning tool that aims at automating the installation and configuration of tools or services on your platform without the usage of agents. This means fast, repeatable setup of one, a group or all instances you have created.<br />
<h3>
Vagrant</h3>
<a href="https://www.vagrantup.com/">HashiCorp Vagrant</a> is an environment deployment tool to create virtual environments using <a href="https://www.virtualbox.org/">Virtualbox</a> or <a href="https://www.vmware.com/">VMWare</a> on a local system. It's great for creating local development environments and works great with <a href="https://www.ansible.com/">RedHat Ansible</a> to provision these virtualised platforms.<br />
<h3>
Docker</h3>
<a href="https://www.docker.com/">Docker</a> containers are small, computational units of software, packaged as a platform with OS, network and application, that run everywhere the same way. Because there's no virtualisation layer between your application and your OS, applications run faster and require less resources. Even though Docker containers are great for development of micro-services, we now see more and more containers being deployed in production.<br />
<h3>
Kubernetes</h3>
<a href="https://kubernetes.io/">Kubernetes</a> is an open source container orchestration technology that allows you to manage, scale and deploy containers with ease. If you're already using <a href="https://www.docker.com/">Docker</a> containers, managing them with Kubernetes is highly advisable.<br />
<h2>
Next steps</h2>
Now that we have defined how we should structure our documentation, what aspects we need to focus on to make our application secure by design and how automation can help us ensuring that we have repeatable setup, provisioning and configuration of our infrastructure as code, we should get started applying what we have seen so far onto a real project.<br />
<br />
In my next article I will document a web application project and provide examples how this would look like with the suggestions described in this article. Hope to see you next time.M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com0tag:blogger.com,1999:blog-28215292.post-72806451195829409632019-02-08T15:10:00.000+01:002019-02-08T15:36:22.974+01:00Getting to understand the basics of securityIn this article I first try to understand what security is and what are best security practices for web applications.<br />
<br />
In my previous article <a href="https://www.dragonbe.com/2018/12/the-challenge-for-2019-has-just-got-real.html">"The challenge for 2019 has just got real"</a> I had set a challenge for myself in 2019: to learn more about securing web applications in general and PHP web applications in specific.<br />
<br />
In this article we're going to explore what security means and what basic steps should be considered in providing security. After all we want to incorporate security in our design and development process instead of trying to bold it on at the end.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwA5ILZvG0lF3YNXctXIXOKPeUQb2cRDAoWh9NAqoja2rDXmKzGaDljxel5g4rIO08zB9EJNw-FZRd_fMTjczJ1Gb3eoCt7pIzM0eqBll_XiNGjKkEnnhtHGgUTYONNlU_FRn-3A/s1600/securing_php_apps.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="388" data-original-width="699" height="354" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwA5ILZvG0lF3YNXctXIXOKPeUQb2cRDAoWh9NAqoja2rDXmKzGaDljxel5g4rIO08zB9EJNw-FZRd_fMTjczJ1Gb3eoCt7pIzM0eqBll_XiNGjKkEnnhtHGgUTYONNlU_FRn-3A/s640/securing_php_apps.png" width="640" /></a></div>
<br />
<h2>
What is security?</h2>
<blockquote>
Security is freedom from, or resilience against, potential harm (or other unwanted coercive change) caused by others.</blockquote>
This quote is taken from <a href="https://en.wikipedia.org/wiki/Security">WikiPedia</a> where in my opinion the goal of security is very well described.<br />
<ul>
<li>Security should provide freedom for the related party</li>
<li>Security should create a resilience against harm or unwanted change caused by others</li>
</ul>
What I'm missing in this quote is the fact it also safeguards and protects valuable assets or people. But I might confuse security with safety, where the latter is aimed to keep items or living organisms safe from harm.<br />
<br />
Looking at the goal of my exploration, building secure web applications, I need to understand the basics of good security practices. I found <a href="https://www.darkreading.com/operations/back-to-basics-10-security-best-practices/a/d-id/1322053">DarkReading: Back To Basics: 10 Security Best Practices</a> where the author lists ten things you need to consider in regards to security:<br />
<ol>
<li>Patch</li>
<li>Limit</li>
<li>Check</li>
<li>Segment</li>
<li>Automate</li>
<li>Visualise</li>
<li>Document</li>
<li>Align</li>
<li>Educate</li>
<li>Measure</li>
</ol>
<h2>
My interpretation of security best practices</h2>
I believe these are good first basics to get started, but I would like to have them ordered differently. In terms of securing a typical web application, I need to look these steps a bit differently.<br />
<h3>
1. Document</h3>
I should document the design of my application. This means I should detail the platform (a part of) the application will run on, what sort of tools or services should be present and what ports are required. And this should be done for each aspect of the application. If we split up responsibilities of the application, we might want to include which pieces of the application should connect with each other and in which direction.<br />
<h3>
2. Align</h3>
I always tell people that good agreements make better friends. This is why documentation is so important in any endeavour you're embarking on. The documentation should also specify what is expected by anyone on the team so everyone knows who's responsible for what and what will be the result of their work. A good distribution of skills and experience should create an awesome team.<br />
<br />
Of course, the people that are part of the team you're working with should feel comfortable in the role they were given and they should feel a valued member of this team.<br />
<h3>
3. Automate</h3>
If we automate the setup of our platform and application from the beginning, we already have a playbook to get started with those things we should optimise over time like software updates and automated deployments. This automation should set up the infrastructure, remove the pre-installed bulk of services, tools and libraries (clean slate), update the platform to the latest version and install only required components we need on it.<br />
<h3>
4. Segment</h3>
Because a web application consists of different purpose areas we want to segment these areas as much as possible and apply the concept of single-responsibility. All this is handled by our automation step.<br />
<h3>
5. Limit</h3>
Since this segmentation flows naturally into limitation, we can ensure that we define rules how segmented components should interact with each other, what connections we allow inbound and outbound, and which users (if any) should have access to these resources. Again, automation should make this a trivial process.<br />
<h3>
6. Patch</h3>
We need to ensure we're always running the latest version of the OS, library, tool or service we're using and when patches are available, this update should be easy to apply. Considering it's a repetitive process, we should automate this.<br />
<h3>
7. Monitor</h3>
Alongside the installation of required OS, tools, services and libraries, special attention need to be put in monitoring of these systems. Upfront you should define metrics that you will measure, how you can distinguish normal telemetry from abnormalities and how you're going to alert on these abnormalities.<br />
<br />
Given that you can not secure a system 100%, you need to be able to discover intrusions and have a remediation plan ready.<br />
<h3>
8. Visualise</h3>
Your whole infrastructure should be visible from every layer:<br />
<ul>
<li>your network</li>
<li>your platforms</li>
<li>your monitoring</li>
<li>your application</li>
</ul>
These application diagrams provide useful information for your team to pinpoint weakest links in your architecture.<br />
<h3>
9. Check</h3>
In the article the author used this part to enforce policies, but I would disagree. Checking things should be a process where expectations should be verified.<br />
<br />
At one point you have a working environment with a variety of platforms, networks, services and applications. If you want to know for sure they are meeting your requirements, testing for these requirements is your only option.<br />
<br />
With my background in testing I would suggest that you apply a few testing approaches to ensure the running architecture meets your expectations, preferably in an automated way.<br />
Some of the tools I can think of:<br />
<ul>
<li><strong>Provisioner Linting:</strong> For each of the provisioners (Ansible, Puppet, Chef, …) there exists a linting tool to validate your automated provisioning scripts</li>
<li><strong>OS Checker:</strong> To verify the OS we like to use <code><a href="https://insecure.org/" rel="nofollow" target="_blank">nmap</a></code> because we can fingerprint the OS without even accessing the system</li>
<li><strong>Port Scan:</strong> A common skipped phase is to ensure that only ports are open required for the application to operate. We also use <code><a href="https://insecure.org/" rel="nofollow" target="_blank">nmap</a></code> here to ensure that we have the right ports open while others are closed. As a bonus, you can even verify if the segmented elements in your architecture are unreachable</li>
<li><strong>Performance benchmarking:</strong> To ensure we can keep improving our solutions, we introduce performance benchmarking at the beginning of every assignment so we can see when a change we introduce is reducing performance.</li>
<li><strong>Resilience testing:</strong> It's no secret that I'm a fan of the <a href="https://netflix.github.io/chaosmonkey/">Netflix Chaos Monkey</a>, so I include it to build in resilience from the start.</li>
<li><strong>Common tests:</strong> With common tests I group the table-stakes of testing applications. These are:<ul>
<li>Unit testing</li>
<li>Behaviour testing</li>
<li>Acceptance testing</li>
<li>End-to-end testing</li>
<li>Functional testing</li>
</ul>
</li>
<li><strong>Security testing:</strong> Since this is a new field I need to explore further, I will come back to this aspect in future posts.</li>
</ul>
<h3>
10. Educate</h3>
Knowledge sharing is one of the most important aspects of a thriving team. We use <a href="https://phacility.com/phabricator/">Phabricator</a> as our central activity hub. This is where the code lives, commits are reviewed, documentation is written, projects and team formed and so much more. By creating a blameless environment with transparent communication for everyone, we are able to educate everyone in the team on every aspect of a project.<br />
<h2>
Summary</h2>
We now have a better understanding what security means and what we should do to improve the security of web applications. In next articles we're going to break down each suggested action and work our way towards a more secure, robust and performing web application architecture. Until next time.M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com1tag:blogger.com,1999:blog-28215292.post-57837112544704528812018-12-30T12:47:00.000+01:002018-12-31T08:49:59.616+01:00A word about my Have I Been Pwned package<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhG7B_9hAc_iPXL52nOE-MFf0unZQF6APvRBfimkJ1mJN8gaHGiBRyFvC9BSGwO1lInnRZiK6uvMZxSMO3fZLjt08ZQVp9Rsg4Bt0f1MHa_bTc48EavprMJvKj0rJpIjcUnywC1rw/s1600/Have-I-Been-Pwned-Sticker-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="hibp" border="0" data-original-height="408" data-original-width="629" height="414" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhG7B_9hAc_iPXL52nOE-MFf0unZQF6APvRBfimkJ1mJN8gaHGiBRyFvC9BSGwO1lInnRZiK6uvMZxSMO3fZLjt08ZQVp9Rsg4Bt0f1MHa_bTc48EavprMJvKj0rJpIjcUnywC1rw/s640/Have-I-Been-Pwned-Sticker-2.png" title="Have I been pwnd" width="640" /></a></div>
<br />
Yesterday evening I posted a Tweet about improving user entered passwords using <a href="https://www.troyhunt.com/" rel="nofollow" target="_blank">Troy Hunt</a>'s service <a href="https://haveibeenpwned.com/" rel="nofollow" target="_blank">Have I Been Pwnd</a>.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="margin-left: auto; margin-right: auto;"><a href="https://twitter.com/DragonBe/status/1079147918068772870" rel="nofollow" target="_blank"><img alt="Improve password security" border="0" data-original-height="1254" data-original-width="1190" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXmlIg6BKKeGOxIn9ffhpOx5cpMcDjPZXSxuCW_byssa3PxATXhwdFHraxj_LNT5kCe3OCfOmRTJ-Qu71h_nviMHAYagDSFTdo7hA1rXiMaVIponEraE2T-pHcT1X4pD3Ld80yMw/s640/dragonbe-hibp-package.png" title="Promoting my dragonbe/hibp package using Have I Been Pwnd service" width="607" /></a></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><a href="https://twitter.com/DragonBe/status/1079147918068772870" rel="nofollow" target="_blank">A promotional tweet about my dragonbe/hibp package</a></td></tr>
</tbody></table>
It went viral over night with many likes and retweets. But I also got a ton of questions regarding the usage and the security of this package. It turns out many people are scared to send passwords over the internet and are afraid to just use a package (like mine) for password checking.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL2wAtNxg9ohbrJHKkeFt90krAVRz6etYTBtd3kbi4L_WCMPXJGmrqEH2EJd3LdQBabBUijnxgHM1r35TouRutBHCwpXFm0UovOKQoz-OPWgl0boYzcLQjYP8pEwC-6IAOK81sPA/s1600/dragonbe-hibp-package-questions.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="secure question 1" border="0" data-original-height="624" data-original-width="1238" height="322" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL2wAtNxg9ohbrJHKkeFt90krAVRz6etYTBtd3kbi4L_WCMPXJGmrqEH2EJd3LdQBabBUijnxgHM1r35TouRutBHCwpXFm0UovOKQoz-OPWgl0boYzcLQjYP8pEwC-6IAOK81sPA/s640/dragonbe-hibp-package-questions.png" title="Sending passwords over the internet is that secure" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8kovbuvGc_nvHLh9osD9u0xpjnqg-5VD04ffLS8eT89SyaoLI_-wUw1vhgNpDZ5y_hqnOs76-dggY4GDL4x11lBnKSL4G-1tq3qICzmeZyvBkRQW74vXWsdxRNFsVM5lnUk3RDA/s1600/dragonbe-hibp-package-secure.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="secure question 2" border="0" data-original-height="444" data-original-width="1230" height="230" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8kovbuvGc_nvHLh9osD9u0xpjnqg-5VD04ffLS8eT89SyaoLI_-wUw1vhgNpDZ5y_hqnOs76-dggY4GDL4x11lBnKSL4G-1tq3qICzmeZyvBkRQW74vXWsdxRNFsVM5lnUk3RDA/s640/dragonbe-hibp-package-secure.png" title="Security question" width="640" /></a></div>
<br />
<br />
Just to give you an idea of how Have I Been Pwnd service works, I created this little diagram to visualise how I'm using the service.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrLrIWOav-4pJdCEL8glzmqS-6sHBl5DgZX69KrDySxpAxl5xj_DSOXPUGiBuFOGdO58kqWE_bbeudHQRwy-9QANEaJDCcX6FWp-3qEbZ3LHfkwkPsgn-GE9XaxpKvsemx8YAF1A/s1600/hibp-service-diagram.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="650" data-original-width="828" height="502" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrLrIWOav-4pJdCEL8glzmqS-6sHBl5DgZX69KrDySxpAxl5xj_DSOXPUGiBuFOGdO58kqWE_bbeudHQRwy-9QANEaJDCcX6FWp-3qEbZ3LHfkwkPsgn-GE9XaxpKvsemx8YAF1A/s640/hibp-service-diagram.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Visual representation of using HIBP service</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
A user enters their password in our registration or password renewal form. We create a SHA1 hash from it and send the first 5 characters of that hash to HIBP. We get a list of hashes back and a count of how many times this hash has been found in the HIBP database. On our server we lookup the remaining hash against the list we received from HIBP and if there's a match, we return the count back to the user.<br />
<br />
No passwords are sent in the clear over the internet.<br />
No full hashes are exposed to Have I Been Pwned.<br />
All verification happens on the server where the user enters their password.<br />
<br />
To give you an idea how this looks in PHP code, here's a real simple example. BEWARE: this is just code used as an example! Do not copy/paste it and use it in production as it has no filtering and validation of input values!!!<br />
<br />
<pre style="background-color: #202020; border-radius: 2px; box-sizing: border-box; caret-color: rgb(204, 204, 204); color: #cccccc; font-family: iAWriterMono, monospace; font-size: 0.94em; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code class="php" style="border-radius: 2px; box-sizing: border-box; font-family: iAWriterMono, monospace; font-size: 0.94em; padding: 0px;"><?php
header('Content-Type: application/json');
$uri = 'https://api.pwnedpasswords.com/range';
$string = $_GET['string'];
$hash = strtoupper(sha1($string, false));
$subHash = substr($hash, 0, 5);
if (3 > strlen($string)) {
echo json_encode(['hash' => $hash, 'count' => 0]);
exit(0);
}
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_HTTPGET => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 20,
CURLOPT_USERAGENT => 'In2qa/0.0.1-Alpha',
CURLOPT_URL => sprintf('%s/%s', $uri, $subHash),
CURLOPT_HTTPHEADER => [
'Accept' => 'application/vnd.haveibeenpwned.v2+json',
'Access-Control-Allow-Origin' => 'https://api.pwnedpasswords.com',
'Access-Control-Max-Age' => '3628800',
'Access-Control-Allow-Methods' => 'GET',
],
]);
$response = curl_exec($ch);
$response = str_replace("\r\n", PHP_EOL, $response);
$data = explode(PHP_EOL, $response);
$result = array_filter($data, function ($value) use ($hash, $subHash) {
list ($sha1, $count) = explode(':', $value);
$lookup = $subHash . $sha1;
return ($hash === $lookup);
});
if ([] === $result) {
echo json_encode(['hash' => $hash, 'count' => 0]);
exit(0);
}
$response = array_pop($result);
list ($sha1, $count) = explode(':', $response);
echo json_encode(['hash' => $hash, 'count' => $count]);
exit(0);
</code></pre>
<div>
<br /></div>
To facilitate the usage of this service with added filtering and validation of input values, I've created a simple <a href="https://packagist.org/packages/dragonbe/hibp" rel="nofollow" target="_blank">Composer package: "dragonbe/hibp"</a>, which you can find on <a href="https://github.com/DragonBe/hibp" rel="nofollow" target="_blank">GitHub</a> as well.<br />
<br />
To summarise:<br />
<br />
<ul>
<li>No passwords are shared with HIBP</li>
<li>All checks occur within your own web application</li>
<li>You can do things manually, I just provided a package to make it easier</li>
</ul>
<div>
I am not in a business of stealing passwords or hijacking your good password processes and policies. The composer package "<a href="https://packagist.org/packages/dragonbe/hibp" rel="nofollow" target="_blank">dragonbe/hibp</a>" was build to make it easy for everyone to implement this very powerful service provided by <a href="https://www.troyhunt.com/" rel="nofollow" target="_blank">Troy Hunt</a>. I was doing my bit to make the internet a safer place for everyone.</div>
<div>
<br /></div>
<div>
Why would you implement <a href="https://haveibeenpwned.com/" rel="nofollow" target="_blank">Have I Been Pwnd</a> service on your web application?</div>
<div>
Not everyone who uses a computer is aware that strong passwords is a hard job and password managers are not mandatory by law or installed by default by OS vendors: don't expect everyone to apply good password hygiene.</div>
<div>
<br /></div>
<div>
By ensuring your users have passwords that are strong enough and not yet found in earlier breaches (see <a href="https://haveibeenpwned.com/" rel="nofollow" target="_blank">Have I Been Pwnd</a>), you can at least ensure that if someone's user account and password are compromised, it cannot be used against your own application or service. It's not a 100% guarantee bad guys aren't exploiting your user's accounts, but at least it makes it harder to compromise based on earlier breaches.</div>
M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com0tag:blogger.com,1999:blog-28215292.post-37776116360393000182018-12-20T22:54:00.000+01:002018-12-20T22:54:05.798+01:00The challenge for 2019 has just got real<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi82NTktRoxNcivQneiT7GLV8f3woHwL9Y9sBcnOx9hP2slrf78vtCEWYnIRvAK21aLPS5Wg01Gf_1rscl26Xx1tBuSulPTJDFMTqTCXaeVVPmWurIvNDKYliXP0f1Xl5uf3lyKVg/s1600/securing_php_apps.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="PHPSecDev" border="0" data-original-height="388" data-original-width="699" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi82NTktRoxNcivQneiT7GLV8f3woHwL9Y9sBcnOx9hP2slrf78vtCEWYnIRvAK21aLPS5Wg01Gf_1rscl26Xx1tBuSulPTJDFMTqTCXaeVVPmWurIvNDKYliXP0f1Xl5uf3lyKVg/s1600/securing_php_apps.png" title="Securing PHP Apps, the challenge" /></a></div>
<br />
I am a regular listener to the <a href="https://securityweekly.com/" rel="nofollow" target="_blank">Security Weekly Podcasts Network</a>, that includes Hack Naked News, Business Security Weekly, Enterprise Security Weekly, Secure Digital Life and Application Security Weekly. I really love their shows and over the years I've been listening to them, I learned a lot about business leadership, communication and security. If you're in tech, I can highly recommend listening to their podcasts. And since I'm always on the go, these are great shows to listen to while driving around.<br />
<br />
But… and here it comes: for some reason they have a love-hate relationship with PHP, where their disliking of the technology is omnipresent in their shows. Particularly in their Application Security Weekly they love to pick on PHP and blame it for all the evil that exists on the internet. On one hand, I cannot blame them since the strength of PHP lies in the fact that anyone can write a dynamic website within a few minutes. The downside is also that anyone can write a dynamic website within a few minutes. So I understand where they are coming from. Do I like it? Nope.<br />
<br />
During episode "<a href="https://itunes.apple.com/be/podcast/pauls-security-weekly/id91472687?mt=2&i=1000426107232" rel="nofollow" target="_blank">In Flames - Application Security Weekly #44</a>" they were picking on WordPress that released version 5.0.1 with a series of security updates for version 5.0.0 that was released a couple of days earlier. The host <a href="https://twitter.com/andMYHacks" rel="nofollow" target="_blank">Keith Hoodlet</a>'s comment "WordPress, you should have this down by now, I think" got me all fired up.<br />
<br />
I'm not knees deep in the inner workings of WordPress, but I do know that it's a vibrant, active community that just want to give users the best experience for the many users worldwide. The only time many security researchers are actually looking at the code (and vulnerabilities) is when the code is released. If half of them would take part in the development process before the release is done publicly, many of these issues can be tackled upfront.<br />
<br />
But that's the thing with open source: people expect that everyone is on top of all the things and that you are fixing bugs in an instant. I've been in professional development since 1990 and I've seen over the past decades the industry putting more and more requirements on developers but not providing them the time to actually learn properly what needs to be known resulting in an ever lasting chase of the technology rabbit. Those who actually invest large portions of their off-work time to learn and adapt, understand what gap needs to be filled.<br />
<br />
So after listening to the rants of both the show hosts <a href="https://twitter.com/securityweekly" rel="nofollow" target="_blank">Paul Asadoorian</a> and <a href="https://twitter.com/andMYHacks" rel="nofollow" target="_blank">Keith Hoodlet</a>, I decided it was time for me to take on a new challenge for myself and the PHP community I love so much: I need to learn the security aspect of web application development in general and PHP in specifics so I can educate and mentor those in the community to build more secure, robust PHP applications so by the end of 2019 I can convince Paul and Keith that PHP is as secure as any other technology stack out there.<br />
<br />
I don't know what I'm getting myself into as I have only a basic understanding of web application security (<a href="https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project" rel="nofollow" target="_blank">OWASP Top 10</a>, <a href="https://www.owasp.org/index.php/Web_Application_Security_Testing_Cheat_Sheet" rel="nofollow" target="_blank">OWASP Web Application Security Testing Cheat Sheet</a>, <a href="https://secure.php.net/manual/en/security.php" rel="nofollow" target="_blank">PHP Security</a>, <a href="http://phpsec.org/library/" rel="nofollow" target="_blank">PHP Security Consortium</a> and the <a href="https://www.martinfowler.com/articles/web-security-basics.html" rel="nofollow" target="_blank">Basics of Web Application Security by Martin Fowler</a>. I was also lucky that my compony partnered with <a href="https://www.ripstech.com/" rel="nofollow" target="_blank">RIPSTech</a> who have a superb security scanner for all sorts of PHP vulnerabilities, and I love their annual <a href="https://www.ripstech.com/php-security-calendar-2018/" rel="nofollow" target="_blank">PHP Security Advent Calendar</a> where each day of December they are challenging the audience to identify the vulnerability.<br />
<br />
Let me use this blog to share my experiences as I go through the process of learning security and I'm reaching out to my friends in the PHP and Testing community to come to my aid to point me to things I'm not yet aware of (the dreadful unknown unknowns). And hopefully I become a wiser developer by the end of 2019 so I can convince the hosts of Application Security Weekly that PHP is not better and not worse than any other technology.M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com1tag:blogger.com,1999:blog-28215292.post-49112880808880869192018-05-02T08:30:00.000+02:002018-05-04T00:51:20.585+02:00Testing your e-commerce PHP application<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBFzLqCOjue0gyhio8Vdob9UHSwWGiLgFXKoU4dDI3a2SzVWmG0TagJZtgEUmHoZS0qyQ_GhlLlhFXZB_8Z-4DRSuIoRHpEWWHoGxLgwxd5iIyPHYqjObns4RTM0xnGtK0eMUqHw/s1600/30daysoftesting_e-commerce_testing.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="#30daysoftesting" border="0" data-original-height="1200" data-original-width="1600" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBFzLqCOjue0gyhio8Vdob9UHSwWGiLgFXKoU4dDI3a2SzVWmG0TagJZtgEUmHoZS0qyQ_GhlLlhFXZB_8Z-4DRSuIoRHpEWWHoGxLgwxd5iIyPHYqjObns4RTM0xnGtK0eMUqHw/s640/30daysoftesting_e-commerce_testing.jpg" title="E-Commerce Testing with SauceLabs and Ministry of Testing" width="640" /></a></div>
<br />
I'm participating (as much as possible) in the <a href="https://twitter.com/search?l=&q=%2330daysoftesting&src=typd" rel="nofollow" target="_blank">#30daysoftesting</a> challenge organised by <a href="https://www.ministryoftesting.com/" rel="nofollow" target="_blank">Ministry of Testing</a> and <a href="https://saucelabs.com/" rel="nofollow" target="_blank">SauceLabs</a>. If you're interested, read the full <a href="https://dojo.ministryoftesting.com/dojo/lessons/30-days-of-e-commerce-testing" rel="nofollow" target="_blank">30 Days of E-Commerce Testing article</a> and join this fun and educational challenge.<br />
<br />
The 2nd challenge on the list was to read and share interesting blog articles about<b> E-commerce testing</b>. Since I'm working as a PHP professional I thought it would be great if I oriented my focus on testing PHP based E-commerce platforms. I picked <a href="https://woocommerce.com/" rel="nofollow" target="_blank">WooCommerce</a> as it's an easy to install and use E-commerce solution. For <a href="https://www.magento.com/" rel="nofollow" target="_blank">Magento</a>, <a href="https://www.prestashop.com/" rel="nofollow" target="_blank">PrestaShop</a> and others I've added useful links at the bottom of this article.<br />
<br />
<h3>
WooCommerce</h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijCl08C3_sfY34djuYrBdzqHqSLU7AJXGHBS4lieJeJcX0uhuEpiDRUTj-opkoWXacYYBfXUDN32SxWESEzVz1z0r2IEn0Mm84KFTe80ZWL0NdIwZXQLfDoG8b_kq5poEcfWZ1zQ/s1600/Screenshot+2018-05-01+14.34.26.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="WooCommerce Homepage" border="0" data-original-height="900" data-original-width="1440" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijCl08C3_sfY34djuYrBdzqHqSLU7AJXGHBS4lieJeJcX0uhuEpiDRUTj-opkoWXacYYBfXUDN32SxWESEzVz1z0r2IEn0Mm84KFTe80ZWL0NdIwZXQLfDoG8b_kq5poEcfWZ1zQ/s640/Screenshot+2018-05-01+14.34.26.png" title="WooCommerce Homepage" width="640" /></a></div>
<br />
<a href="https://woocommerce.com/" rel="nofollow" target="_blank">WooCommerce</a> is an add-on for <a href="https://www.wordpress.org/" rel="nofollow" target="_blank">WordPress</a>, allowing you to integrate E-commerce functionality directly within your blog. This ensures you can be up-and-running in no-time. Even though WooCommerce and WordPress are very active community-driven projects, they both suffer from legacy that has been carried along with WordPress since it's origin: it wasn't build with testing in mind.<br />
<br />
Don't get me wrong, the latest versions of WooCommerce and WordPress have unit tests, but their users and integration community was never engaged to automate tests or have taken on a habit of testing. Both platforms come equipped with all the tools required for automated testing when you check out the development code. Production code for the general public do not include these tests. Maybe that's why there's not such a testing culture on these projects.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAWWmJ9eySbxOorXxy9FZCRjQa2tfOOszCkvWKDNQ0BPeVLo6d24Kx4pPbdlzkq5ltR0YyjHw95EPgNrEq6l92DbE62eK_RNMoOqVXv3X47NKqryVRlnIHVnq45tGXFlvr4bJPIA/s1600/Screenshot+2018-05-01+12.24.39.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="WordPress PHPUnit tests" border="0" data-original-height="514" data-original-width="682" height="481" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAWWmJ9eySbxOorXxy9FZCRjQa2tfOOszCkvWKDNQ0BPeVLo6d24Kx4pPbdlzkq5ltR0YyjHw95EPgNrEq6l92DbE62eK_RNMoOqVXv3X47NKqryVRlnIHVnq45tGXFlvr4bJPIA/s640/Screenshot+2018-05-01+12.24.39.png" title="Running PHPUnit tests on WordPress Core" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Running PHPUnit tests on WordPress Core</td></tr>
</tbody></table>
<br />
<br />
If you like to know more about testing WordPress (and fixing bugs), check out their "<a href="https://make.wordpress.org/core/handbook/testing/automated-testing/phpunit/" rel="nofollow" target="_blank">Make WordPress Core Handbook</a>" as it will give you step-by-step instructions how to get started testing WordPress.<br />
<br />
On top of WordPress sits WooCommerce as a plugin (or add-on). Where WordPress offers a step-by-step guide to prepare for testing, WooCommerce offers a <a href="https://github.com/woocommerce/woocommerce/wiki/Core-Testing-Checklist" rel="nofollow" target="_blank">Core Testing Guide on their GitHub Wiki.</a> Setting your environment up for testing WooCommerce is a little bit tricky following their guide only, but luckily <a href="https://jonmoblog.wordpress.com/2017/04/27/automated-testing-for-woocommerce-intro/comment-page-1/" rel="nofollow" target="_blank">Jon Moore has a detailed blog article</a> written for unit and end-to-end testing WooCommerce that you can use as a guide to automatically test your WooCommerce application.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoLI4wWKdsecmw5J60j7GN_0Ew0hg8SnuRZyw815LiK2u_oK9xcCWNCaeUxgwlCQ9kj0r43RZNIfYDJVQqyfsTrPLi-OI-i1eHFMusLHrfOaN3G0lL4MXj0Bi8fuZvk8otsv1J3w/s1600/Screenshot+2018-05-01+13.46.20.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="WooCommerce PHPUnit tests" border="0" data-original-height="514" data-original-width="682" height="482" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoLI4wWKdsecmw5J60j7GN_0Ew0hg8SnuRZyw815LiK2u_oK9xcCWNCaeUxgwlCQ9kj0r43RZNIfYDJVQqyfsTrPLi-OI-i1eHFMusLHrfOaN3G0lL4MXj0Bi8fuZvk8otsv1J3w/s640/Screenshot+2018-05-01+13.46.20.png" title="Running unit tests for WooCommerce" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Running PHPUnit tests on WooCommerce</td></tr>
</tbody></table>
<br />
<br />
<h3>
Other PHP E-commerce platforms</h3>
As mentioned earlier, there are several other E-commerce platforms besides WooCommerce on WordPress: <a href="https://www.magento.com/" rel="nofollow" target="_blank">Magento</a>, <a href="https://www.prestashop.com/" rel="nofollow" target="_blank">PrestaShop</a>, <a href="https://www.opencart.com/" rel="nofollow" target="_blank">OpenCart</a>, <a href="https://sylius.com/" rel="nofollow" target="_blank">Sylius</a>, <a href="https://aimeos.org/" rel="nofollow" target="_blank">Aimeos</a> and many more. I'm not going in detail about their functionality and features, instead I'm more interested in their testing culture and how they allow developers and users to automate their tests.<br />
<h4>
Magento Testing Resources</h4>
<br />
<ul>
<li><a href="http://devdocs.magento.com/guides/v2.1/test/testing.html" rel="nofollow" target="_blank">Magento Testing Guide - Magento</a></li>
<li><a href="http://docs.magento.com/m1/ce/user_guide/magento/magento-test-framework.html" rel="nofollow" target="_blank">Magento Test Framework - Magento</a></li>
<li><a href="http://devdocs.magento.com/guides/v2.0/mtf/mtf_introduction.html" rel="nofollow" target="_blank">Introduction to the Functional Testing Framework - Magento</a></li>
<li><a href="https://magehit.com/blog/how-to-perform-automated-testing-in-magento-2/" rel="nofollow" target="_blank">How to perform automated testing in Magento 2? - MageHit</a></li>
</ul>
<h4>
PrestaShop Testing Resources</h4>
<div>
<ul>
<li><a href="https://developers.prestashop.com/themes/distribution/testing.html" rel="nofollow" target="_blank">PrestaShop Theme Testing - PrestaShop</a></li>
<li><a href="http://build.prestashop.com/news/prestashop-test-framework/" rel="nofollow" target="_blank">The PrestaShop Test Framework - PrestaShop</a></li>
<li><a href="https://www.mockingfish.com/blog/how-to-ab-test-a-prestashop-site-and-why-is-it-important/" rel="nofollow" target="_blank">How to A/B test a PrestaShop site, and why is it important? - MockingFish</a></li>
</ul>
<h4>
Other PHP E-commerce Testing Resources</h4>
<div>
<ul>
<li><a href="https://github.com/opencart/opencart/tree/master/tests" rel="nofollow" target="_blank">OpenCart Tests Readme - GitHub</a> (including call for help)</li>
<li><a href="https://www.sitepoint.com/sylius-and-cutting-your-teeth-on-tdd/" rel="nofollow" target="_blank">Sylius and Cutting Your Teeth on TDD - SitePoint</a></li>
<li><a href="http://lakion.com/blog/testing-and-bdd-in-symfony-sylius-interview-by-fernando-arconada" rel="nofollow" target="_blank">Testing and BDD in Symfony & Sylius (Interview by Fernando Arconada) - Lakion</a></li>
<li><a href="https://aimeos.org/docs/Laravel/Test_installation" rel="nofollow" target="_blank">Laravel/Test installation - Aimeos</a></li>
</ul>
</div>
<h3>
Final thoughts</h3>
</div>
<div>
We see that these mentioned E-commerce projects are seeing the importance of testing and are working hard to improve their code coverage. After all, it's in their best interest to ensure that their users can sell and ship products and get paid in return for their products and/or services. Nobody wants to loose money.</div>
<div>
<br /></div>
<div>
But we also see that the adaption of tests by users, integrators or hosting companies is not their primary focus. Doing research to get started with testing a commercial web application is not easy, articles are often out-dated or incomplete. </div>
<div>
<br /></div>
<div>
Hopefully with this <a href="https://twitter.com/search?l=&q=%2330daysoftesting&src=typd" rel="nofollow" target="_blank">#30daysoftesting</a> initiative by <a href="https://www.ministryoftesting.com/" rel="nofollow" target="_blank">Ministry of Testing</a> and <a href="https://saucelabs.com/" rel="nofollow" target="_blank">SauceLabs</a> we can get more involvement from the community in testing their E-commerce solutions and make these platforms more robust and resilient.</div>
<div>
<br /></div>
<div>
What are your thoughts? Leave your comments and thoughts below or when communicating over social media use the hashtag #30daysoftesting.</div>
M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com0tag:blogger.com,1999:blog-28215292.post-86688085842460045922018-02-11T21:22:00.000+01:002018-02-11T21:22:02.797+01:00Deploy Docker containers fast to Microsoft Azure<h1 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: calc(1.27778em); letter-spacing: 0.5px; line-height: 1.30435; margin: 0px 0px calc(2.6087em); text-size-adjust: auto; text-transform: uppercase;">
DEPLOY DOCKER CONTAINERS FAST TO MICROSOFT AZURE</h1>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
It’s hard to ignore the fact that<span class="Apple-converted-space"> </span><a href="https://www.docker.com/" style="box-sizing: border-box; color: #1a1a1a;">Docker</a><span class="Apple-converted-space"> </span>is a way to move forward for rapid application development, distributed architectures and microservices.</div>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
For developers<span class="Apple-converted-space"> </span><a href="https://www.docker.com/" style="box-sizing: border-box; color: #1a1a1a;">Docker</a><span class="Apple-converted-space"> </span>offers great advantages as they can build their containers specifically for the task they work on. They grab a base image of a container, modify it for their purpose and prepare the functionality inside the container.</div>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
Quality, testing and security teams now have a single instance to look at and ensure all functional and regulatory requirements are met. System engineers now don’t have to worry about providing a system with the required specs as the container is already provisioned for that purpose.</div>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
<a href="https://www.flickr.com/photos/dragonbe/40193280001/" style="box-sizing: border-box; color: #1a1a1a;"><img alt="Containers in the cloud" src="https://c1.staticflickr.com/5/4762/40193280001_1df407fcdf_o.png" style="border: 0px; box-sizing: border-box; max-width: 100%; vertical-align: top;" /></a></div>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
But where do you deploy your<span class="Apple-converted-space"> </span><a href="https://www.docker.com/" style="box-sizing: border-box; color: #1a1a1a;">Docker</a><span class="Apple-converted-space"> </span>containers? You can set up your existing bare metal infrastructure to allow them to run containers, but this also means you need to learn about securing your container infrastructure, which is not an easy task. Luckily “the cloud” offers container services like<span class="Apple-converted-space"> </span><a href="https://cloud.google.com/" style="box-sizing: border-box; color: #1a1a1a;">Google Cloud</a>,<span class="Apple-converted-space"> </span><a href="https://www.openshift.com/" style="box-sizing: border-box; color: #1a1a1a;">RedHat OpenShift</a><span class="Apple-converted-space"> </span>and<span class="Apple-converted-space"> </span><a href="https://www.heroku.com/" style="box-sizing: border-box; color: #1a1a1a;">Heroku</a>. The most popular cloud solution providers are also stepping into the game of containers.<span class="Apple-converted-space"> </span><a href="https://aws.amazon.com/" style="box-sizing: border-box; color: #1a1a1a;">Amazon Web Services</a><span class="Apple-converted-space"> </span>offers<span class="Apple-converted-space"> </span><a href="https://aws.amazon.com/ecs" style="box-sizing: border-box; color: #1a1a1a;">Elastic Container Services</a><span class="Apple-converted-space"> </span>that allows you deploy your<span class="Apple-converted-space"> </span><a href="https://www.docker.com/" style="box-sizing: border-box; color: #1a1a1a;">Docker</a><span class="Apple-converted-space"> </span>containers directly on their infrastructure.</div>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
In this article I’m looking at how to deploy<span class="Apple-converted-space"> </span><a href="https://www.docker.com/" style="box-sizing: border-box; color: #1a1a1a;">Docker</a><span class="Apple-converted-space"> </span>containers on<span class="Apple-converted-space"> </span><a href="https://azure.microsoft.com/" style="box-sizing: border-box; color: #1a1a1a;">Microsoft Azure</a>. For one because I’m a true fan of their cloud solutions, but also because they truly offer a solution that allows me to take an existing container application “as is” and deploy it into their cloud infrastructure using the command line, without having to add additional configurations in my application code base.</div>
<h2 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: calc(1.16667em); line-height: 1.42857; margin-bottom: calc(1.66667em); margin-top: calc(2.85714em); text-size-adjust: auto;">
Preparation</h2>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: 1.66667; margin-bottom: 0px; margin-top: 0px; text-size-adjust: auto;">
Docker container software</h3>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; text-size-adjust: auto;">
To follow along in this tutorial you need to have<span class="Apple-converted-space"> </span><a href="https://www.docker.com/" style="box-sizing: border-box; color: #1a1a1a;">Docker</a><span class="Apple-converted-space"> </span>installed on your computer. If you don’t have it yet, you can download the community edition for your platform of choice at<span class="Apple-converted-space"> </span><a href="https://www.docker.com/community-edition#/download" style="box-sizing: border-box; color: #1a1a1a;">www.docker.com/community-edition</a>.</div>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: 1.66667; margin-bottom: 0px; margin-top: calc(1.66667em); text-size-adjust: auto;">
Microsoft Azure</h3>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; text-size-adjust: auto;">
You also need to have a<span class="Apple-converted-space"> </span><a href="https://azure.microsoft.com/" style="box-sizing: border-box; color: #1a1a1a;">Microsoft Azure</a><span class="Apple-converted-space"> </span>account. If you don’t have one yet, sign up for a<span class="Apple-converted-space"> </span><span style="box-sizing: border-box; font-weight: 600;">FREE</span><span class="Apple-converted-space"> </span>account at<span class="Apple-converted-space"> </span><a href="https://azure.microsoft.com/en-us/free/" style="box-sizing: border-box; color: #1a1a1a;">azure.microsoft.com/free/</a>.</div>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
I’m using the<span class="Apple-converted-space"> </span><span style="box-sizing: border-box; font-weight: 600;"><a href="https://azure.microsoft.com/" style="box-sizing: border-box; color: #1a1a1a;">Microsoft Azure</a><span class="Apple-converted-space"> </span>CLI SDK</span><span class="Apple-converted-space"> </span>as this allows me to automate the build and deploy my containers using my terminal. Read the details on how to install it at<span class="Apple-converted-space"> </span><a href="https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest" style="box-sizing: border-box; color: #1a1a1a;">docs.microsoft.com/cli/azure</a>. The examples in this blog post are using this CLI SDK.</div>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: 1.66667; margin-bottom: 0px; margin-top: calc(1.66667em); text-size-adjust: auto;">
Demo application</h3>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; text-size-adjust: auto;">
The example application is build using basic<span class="Apple-converted-space"> </span><a href="https://secure.php.net/" style="box-sizing: border-box; color: #1a1a1a;">PHP</a><span class="Apple-converted-space"> </span>and uses a<span class="Apple-converted-space"> </span><a href="https://www.sqlite.org/" style="box-sizing: border-box; color: #1a1a1a;">SQLite</a><span class="Apple-converted-space"> </span>database. The source code is available on my<span class="Apple-converted-space"> </span><a href="https://www.github.com/dragonbe" style="box-sizing: border-box; color: #1a1a1a;">GitHub</a><span class="Apple-converted-space"> </span>account. In order to run the application, we use the vanilla<span class="Apple-converted-space"> </span><a href="https://hub.docker.com/_/php" style="box-sizing: border-box; color: #1a1a1a;">PHP Docker image</a>.</div>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
ACI HelloWorld app is available on<span class="Apple-converted-space"> </span><a href="https://github.com/DragonBe/aci-helloworld" style="box-sizing: border-box; color: #1a1a1a;">DragonBe/aci-helloworld</a>.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">cd /path/to/workspace
git clone https://github.com/DragonBe/aci-helloworld.git
cd aci-helloworld/
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
I’ve based this demo app on the example given on the Microsoft Azure Documentation portal “<a href="https://docs.microsoft.com/en-us/azure/container-instances/container-instances-quickstart" style="box-sizing: border-box; color: #1a1a1a;">Create your first container in Azure Container Instances</a>” and modified it a bit for specific PHP purposes and added a bit more useful example app.</div>
<h2 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: calc(1.16667em); line-height: 1.42857; margin-bottom: calc(1.66667em); margin-top: calc(2.85714em); text-size-adjust: auto;">
Getting started</h2>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
Once you have completed the preparation step, it’s time to get our hands dirty.<span class="Apple-converted-space"> </span></div>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: 1.66667; margin-bottom: 0px; margin-top: calc(1.66667em); text-size-adjust: auto;">
Link your Azure SDK to your Azure subscription</h3>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; text-size-adjust: auto;">
Before we can get started, we need to make sure that we’re using the correct<span class="Apple-converted-space"> </span><a href="https://azure.microsoft.com/" style="box-sizing: border-box; color: #1a1a1a;">Microsoft Azure</a><span class="Apple-converted-space"> </span>account. The best way would be to log in your account on the command line.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">az login
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
If your installation was successful, you will see the following output. Of course, your code will be different.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">To sign in, use a web browser to open the page https://aka.ms/devicelogin and enter the code C9LZEAJ77 to authenticate.
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
This will launch your browser. If you’re not yet logged in for<span class="Apple-converted-space"> </span><a href="https://azure.microsoft.com/" style="box-sizing: border-box; color: #1a1a1a;">Microsoft Azure</a>, you need to provide your credentials first.</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBHdrIgOKZKE7lBOOn55w_sxWfihn84yswUw1B58UkJmKsoM7aB5dBHFgdTBbnLD_-OIPyQNk2Uj2wuBXw5gZv6CtCeai2KFN_QnQVhW-OPKFEoUfMAJOIApLY2dfU2LprMi1cxQ/s1600/Microsoft_Azure_Login_Screen.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Log in on Microsoft Live" border="0" data-original-height="900" data-original-width="1440" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBHdrIgOKZKE7lBOOn55w_sxWfihn84yswUw1B58UkJmKsoM7aB5dBHFgdTBbnLD_-OIPyQNk2Uj2wuBXw5gZv6CtCeai2KFN_QnQVhW-OPKFEoUfMAJOIApLY2dfU2LprMi1cxQ/s400/Microsoft_Azure_Login_Screen.png" title="" width="400" /></a></div>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
Next it will take you to a web page where you can enter your code.</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_8CkXxpTMoBog9clnAhDK7uAOX2_IdYmMQRtiUAA-PkSovT82bFH5-3NDBLSyHFXYuPY84b9RY_5iv1_0dR-EgJJ9mYrEBdAaHqUWY9AWBnxy4APLNkUxbsX1Brhc3tz_i0Y3NQ/s1600/Microsoft_Azure_Cross-platform_Command_Line_Interface.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Enter the application code" border="0" data-original-height="900" data-original-width="1440" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_8CkXxpTMoBog9clnAhDK7uAOX2_IdYmMQRtiUAA-PkSovT82bFH5-3NDBLSyHFXYuPY84b9RY_5iv1_0dR-EgJJ9mYrEBdAaHqUWY9AWBnxy4APLNkUxbsX1Brhc3tz_i0Y3NQ/s400/Microsoft_Azure_Cross-platform_Command_Line_Interface.png" title="" width="400" /></a></div>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
Once verified with Microsoft, you'll get to see your subscription details back into the command line interface.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">[
{
"cloudName": "AzureCloud",
"id": "abcd1234-abcd-1234-abcd-123456abcdef",
"isDefault": true,
"name": "Pay-As-You-Go",
"state": "Enabled",
"tenantId": "1234abcd-1234-abcd-1234-abcdef123456",
"user": {
"name": "michelangelo@in2it.be",
"type": "user"
}
}
]
</code></pre>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: 1.66667; margin-bottom: 0px; margin-top: calc(1.66667em); text-size-adjust: auto;">
Create a resource group</h3>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; text-size-adjust: auto;">
The easiest way to manage your applications is to define a resource group. The purpose of this group is to have all related applications grouped together so it’s easy to enable, scale and disable them referencing a single group name.</div>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
The name for this resource group needs to be unique, so be creative. I was lucky to find<span class="Apple-converted-space"> </span><code style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0.08333em 0.1667em 0.1667em; white-space: pre-wrap;">aciDemoApp</code><span class="Apple-converted-space"> </span>not being used yet, but it could be that the chosen name is already taken. Adding a prefix of your company or a postfix with current date and time can also do the trick. Be creative!</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">az group create --name aciDemoApp --location westeurope
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
Once the resource group is created, you'll get again a confirmation in your command line interface.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">{
"id": "/subscriptions/abcd1234-abcd-1234-abcd-123456abcdef/resourceGroups/aciDemoApp",
"location": "westeurope",
"managedBy": null,
"name": "aciDemoApp",
"properties": {
"provisioningState": "Succeeded"
},
"tags": null
}
</code></pre>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: 1.66667; margin-bottom: 0px; margin-top: calc(1.66667em); text-size-adjust: auto;">
Create an Azure container registry</h3>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; text-size-adjust: auto;">
Because we need to make our image available for<span class="Apple-converted-space"> </span><a href="https://azure.microsoft.com/" style="box-sizing: border-box; color: #1a1a1a;">Microsoft Azure</a><span class="Apple-converted-space"> </span>we create our own container registry.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">az acr create --resource-group aciDemoApp --name aciDemoMvp --sku Basic
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
This command will create an Active Directory account on<span class="Apple-converted-space"> </span><a href="https://azure.microsoft.com/" style="box-sizing: border-box; color: #1a1a1a;">Microsoft Azure</a><span class="Apple-converted-space"> </span>and assigns permissions for your application to access the registry.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">Create a new service principal and assign access:
az ad sp create-for-rbac --scopes /subscriptions/abcd1234-abcd-1234-abcd-123456abcdef/resourceGroups/aciDemoApp/providers/Microsoft.ContainerRegistry/registries/aciDemoMvp --role Owner --password <password>
Use an existing service principal and assign access:
az role assignment create --scope /subscriptions/abcd1234-abcd-1234-abcd-123456abcdef/resourceGroups/aciDemoApp/providers/Microsoft.ContainerRegistry/registries/aciDemoMvp --role Owner --assignee <app-id>
{
"adminUserEnabled": false,
"creationDate": "2018-02-09T14:10:02.075876+00:00",
"id": "/subscriptions/abcd1234-abcd-1234-abcd-123456abcdef/resourceGroups/aciDemoApp/providers/Microsoft.ContainerRegistry/registries/aciDemoMvp",
"location": "westeurope",
"loginServer": "acidemomvp.azurecr.io",
"name": "aciDemoMvp",
"provisioningState": "Succeeded",
"resourceGroup": "aciDemoApp",
"sku": {
"name": "Basic",
"tier": "Basic"
},
"status": null,
"storageAccount": null,
"tags": {},
"type": "Microsoft.ContainerRegistry/registries"
}
</app-id></password></code></pre>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: 1.66667; margin-bottom: 0px; margin-top: calc(1.66667em); text-size-adjust: auto;">
Log in into your Azure container registry</h3>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; text-size-adjust: auto;">
Before we can create our container images and push them into our newly created container registry, we need to login into the Active Directory we just created.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">az acr login --name aciDemoMvp
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
This will return you a successful status message.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">Login Succeeded
</code></pre>
<h2 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: calc(1.16667em); line-height: 1.42857; margin-bottom: calc(1.66667em); margin-top: calc(2.85714em); text-size-adjust: auto;">
Prepare your docker setup</h2>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
Up until this point we have only set up our<span class="Apple-converted-space"> </span><a href="https://azure.microsoft.com/" style="box-sizing: border-box; color: #1a1a1a;">Microsoft Azure</a><span class="Apple-converted-space"> </span>account to accept our containers. But we need to have our containers defined in the first place. So here we’re going to ensure everything is working locally before we push it into the cloud.</div>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: 1.66667; margin-bottom: 0px; margin-top: calc(1.66667em); text-size-adjust: auto;">
Build and run locally</h3>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; text-size-adjust: auto;">
The easiest way to figure out if your<span class="Apple-converted-space"> </span><a href="https://www.docker.com/" style="box-sizing: border-box; color: #1a1a1a;">Docker</a><span class="Apple-converted-space"> </span>container is ready is to build and run it on your workstation.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">docker build . -t aci-tutorial-app
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
Once the build is complete, we can run it to see if everything is working.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">docker run -p 8000:80 --rm --name aci_tutorial_webapp aci-tutorial-app
</code></pre>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: 1.66667; margin-bottom: 0px; margin-top: calc(1.66667em); text-size-adjust: auto;">
Make sure the image is available</h3>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">docker images
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
Should provide you a listing of your current running apps</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">REPOSITORY TAG IMAGE ID CREATED SIZE
aci-tutorial-app latest d24e209f7cb6 2 hours ago 70.7MB
</code></pre>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: 1.66667; margin-bottom: 0px; margin-top: calc(1.66667em); text-size-adjust: auto;">
Tag your image with the Azure Image Registry</h3>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; text-size-adjust: auto;">
Use the following command if you need to find your registry URI that you’ll need to push your image to.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">az acr show --name aciDemoMvp --query loginServer
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
This will give you the URI you can use for tagging your image</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">"acidemomvp.azurecr.io"
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
Now tag your image and make sure you also provide a version (like<span class="Apple-converted-space"> </span><code style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0.08333em 0.1667em 0.1667em; white-space: pre-wrap;">v1</code>) as this will make it easier in the future to scale your application and have clean deployments of your application containers in the cloud.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">docker tag aci-tutorial-app acidemomvp.azurecr.io/aci-tutorial-app:v1
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
Check again your Docker images to see the tag being applied correctly.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">docker images
</code></pre>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">REPOSITORY TAG IMAGE ID CREATED SIZE
acidemomvp.azurecr.io/aci-tutorial-app v1 d24e209f7cb6 2 hours ago 70.7MB
aci-tutorial-app latest d24e209f7cb6 2 hours ago 70.7MB
</code></pre>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: 1.66667; margin-bottom: 0px; margin-top: calc(1.66667em); text-size-adjust: auto;">
Push your Docker image to Azure registry</h3>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; text-size-adjust: auto;">
Now it’s time to push our tagged container image into the<span class="Apple-converted-space"> </span><a href="https://azure.microsoft.com/" style="box-sizing: border-box; color: #1a1a1a;">Microsoft Azure</a>registry.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">docker push acidemomvp.azurecr.io/aci-tutorial-app:v1
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
This might take some time to push your whole image upstream, but once it’s complete you should receive something similar to this.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">The push refers to repository [acidemomvp.azurecr.io/aci-tutorial-app]
f9e1772b82d2: Pushed
9d3a6c539310: Pushed
29e829473f65: Pushed
5df56ca2422c: Pushed
0fe69bd96626: Pushed
4f65eb3ac611: Pushed
8a3436067bb2: Pushed
6443b41f72f9: Pushed
993df43bf684: Pushed
530e50cf94e4: Pushed
86700745f1ec: Pushed
a6f0d3e3e138: Pushed
550c61595337: Pushed
ab779a053abe: Pushed
cec8466f473c: Pushed
d45e3781d4b2: Pushed
8d8f451305fc: Pushed
e416a4904ee4: Pushed
2ec5c0a4cb57: Pushed
v1: digest: sha256:9b59f4b5156a089737ccf440cae52e4e7abd5d0d5db0aec021318f1370f35ddd size: 4285
</code></pre>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: 1.66667; margin-bottom: 0px; margin-top: calc(1.66667em); text-size-adjust: auto;">
Enable administrative rights on the registry</h3>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; text-size-adjust: auto;">
We now enable administrative permissions on our registry so we can actually deploy our container.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">az acr update -n aciDemoMvp --admin-enabled true
</code></pre>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">{
"adminUserEnabled": true,
"creationDate": "2018-02-09T14:10:02.075876+00:00",
"id": "/subscriptions/abcd1234-abcd-1234-abcd-123456abcdef/resourceGroups/aciDemoApp/providers/Microsoft.ContainerRegistry/registries/aciDemoMvp",
"location": "westeurope",
"loginServer": "acidemomvp.azurecr.io",
"name": "aciDemoMvp",
"provisioningState": "Succeeded",
"resourceGroup": "aciDemoApp",
"sku": {
"name": "Basic",
"tier": "Basic"
},
"status": null,
"storageAccount": null,
"tags": {},
"type": "Microsoft.ContainerRegistry/registries"
}
</code></pre>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: 1.66667; margin-bottom: 0px; margin-top: calc(1.66667em); text-size-adjust: auto;">
Get the password needed for deployment</h3>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; text-size-adjust: auto;">
We need to provide a password to run our container on<span class="Apple-converted-space"> </span><a href="https://azure.microsoft.com/" style="box-sizing: border-box; color: #1a1a1a;">Microsoft Azure</a><span class="Apple-converted-space"> </span>cloud. Retrieving it is as simple as querying ACR credentials.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">az acr credential show --name aciDemoMvp --query "passwords[0].value"
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
Will return something like this. Make sure that you keep this password<span class="Apple-converted-space"> </span><span style="box-sizing: border-box; font-weight: 600;">SECRET</span><span class="Apple-converted-space"> </span>as this is your administrative account. You can also use<span class="Apple-converted-space"> </span><a href="https://azure.microsoft.com/en-us/services/key-vault/" style="box-sizing: border-box; color: #1a1a1a;">Microsoft Azure Key Vault</a><span class="Apple-converted-space"> </span>for managing these privileges, but that’s material for another blog article when we discuss identity management.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">"0tXXLUN+/Ye+8RBotZRRst7OU+I=CteG"
</code></pre>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: 1.66667; margin-bottom: 0px; margin-top: calc(1.66667em); text-size-adjust: auto;">
Deploy your docker container</h3>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; text-size-adjust: auto;">
Finally we can deploy our container into production on<span class="Apple-converted-space"> </span><a href="https://azure.microsoft.com/" style="box-sizing: border-box; color: #1a1a1a;">Microsoft Azure</a>container services.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">az container create --resource-group aciDemoApp --name aci-tutorial-app --image acidemomvp.azurecr.io/aci-tutorial-app:v1 --cpu 1 --memory 1 --ip-address public --ports 80 --registry-password "0tXXLUN+/Ye+8RBotZRRst7OU+I=CteG"
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
This command creates the application container and starts running it. In the details you get back from the service you get full details about your deployed container.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">{
"containers": [
{
"command": null,
"environmentVariables": [],
"image": "acidemomvp.azurecr.io/aci-tutorial-app:v1",
"instanceView": null,
"name": "aci-tutorial-app",
"ports": [
{
"port": 80,
"protocol": null
}
],
"resources": {
"limits": null,
"requests": {
"cpu": 1.0,
"memoryInGb": 1.0
}
},
"volumeMounts": null
}
],
"id": "/subscriptions/abcd1234-abcd-1234-abcd-123456abcdef/resourceGroups/aciDemoApp/providers/Microsoft.ContainerInstance/containerGroups/aci-tutorial-app",
"imageRegistryCredentials": [
{
"password": null,
"server": "acidemomvp.azurecr.io",
"username": "acidemomvp"
}
],
"instanceView": {
"events": [],
"state": "Pending"
},
"ipAddress": {
"ip": "40.68.171.88",
"ports": [
{
"port": 80,
"protocol": "TCP"
}
]
},
"location": "westeurope",
"name": "aci-tutorial-app",
"osType": "Linux",
"provisioningState": "Creating",
"resourceGroup": "aciDemoApp",
"restartPolicy": "Always",
"tags": null,
"type": "Microsoft.ContainerInstance/containerGroups",
"volumes": null
}
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
To get the status of your container you can use<span class="Apple-converted-space"> </span><code style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0.08333em 0.1667em 0.1667em; white-space: pre-wrap;">az container show --resource-group aciDemoApp --name aci-tutorial-app --query instanceView.state</code>, which will return you the status.</div>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
Immediately after you’ve started your container, your container needs to boot up.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">"Pending"
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
But shortly after you’ve deployed your container, you’ll see the status indicating everything is a go.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">"Running"
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
To get the IP of your container use<span class="Apple-converted-space"> </span><code style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0.08333em 0.1667em 0.1667em; white-space: pre-wrap;">az container show --resource-group aciDemoApp --name aci-tutorial-app --query ipAddress.ip</code></div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">"40.68.171.88"
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
Now you can point your browser to<span class="Apple-converted-space"> </span><a href="http://40.68.171.88/" style="box-sizing: border-box; color: #1a1a1a;">40.68.171.88</a><span class="Apple-converted-space"> </span>and you should see your web application smiling back to you.</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBEHel0nCGChJoH0dwedxGrGwlSxbpiRXMS-WyxLHkqtztbIolSexcTL-Hf0RdAD7WAiMa_wI5pez0WLr4OGSHQinXTjbE1GGQZLS11cNW88CQq1BtKvEVZKT-y8ICOS62Xfnk3A/s1600/ACI_Demo_App.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Your application smiling back at you" border="0" data-original-height="900" data-original-width="1440" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBEHel0nCGChJoH0dwedxGrGwlSxbpiRXMS-WyxLHkqtztbIolSexcTL-Hf0RdAD7WAiMa_wI5pez0WLr4OGSHQinXTjbE1GGQZLS11cNW88CQq1BtKvEVZKT-y8ICOS62Xfnk3A/s400/ACI_Demo_App.png" title="" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiov_S-MdRzc4xdxp6lH47LpY8uk12t4WvKlC43ztE4oFzk99DM08C2POvV9eg2PPgkR_oiM-_9gbJE9qA0mQoGdnFCXcVaK25fdOne5rnvVEAGpdMQro-2FH2XP6aFVaWQ-FP1Qg/s1600/ACI_Demo_App_Books_v1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="A book recommendation for you" border="0" data-original-height="900" data-original-width="1440" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiov_S-MdRzc4xdxp6lH47LpY8uk12t4WvKlC43ztE4oFzk99DM08C2POvV9eg2PPgkR_oiM-_9gbJE9qA0mQoGdnFCXcVaK25fdOne5rnvVEAGpdMQro-2FH2XP6aFVaWQ-FP1Qg/s400/ACI_Demo_App_Books_v1.png" title="" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: 1.66667; margin-bottom: 0px; margin-top: calc(1.66667em); text-size-adjust: auto;">
See the log output of your container</h3>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">az container logs --resource-group aciDemoApp --name aci-tutorial-app
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
This will give you insights into the container activity</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">listening on port 80
::ffff:10.240.255.106 - - [10/Feb/2018:10:47:10 +0000] "GET /favicon.ico HTTP/1.1" 404 150 "http://13.95.165.162/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
::ffff:10.240.255.105 - - [10/Feb/2018:10:50:07 +0000] "GET / HTTP/1.1" 200 1663 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: 1.66667; margin-bottom: 0px; margin-top: calc(1.66667em); text-size-adjust: auto;">
In your <a href="https://portal.azure.com/" rel="nofollow" target="_blank">Microsoft Azure Portal</a> you can see the container resource group up and running with a whole bunch of more details.</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhy1QZlGCfX0xRkHYxl2ht5vJuaCc3dmQwyHUtcPSKOAzPHnY2zRc7Tw7Ghqy9c8xO8iY-Q487qAuQJTLGMaJ3Rc0U5d03u-P0hD8SwmsHho839RoxFS1IpRPiVy7i45nXpdURkCA/s1600/Azure_Portal_ACI_Demo_App.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Your containers in Microsoft Azure Portal" border="0" data-original-height="900" data-original-width="1440" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhy1QZlGCfX0xRkHYxl2ht5vJuaCc3dmQwyHUtcPSKOAzPHnY2zRc7Tw7Ghqy9c8xO8iY-Q487qAuQJTLGMaJ3Rc0U5d03u-P0hD8SwmsHho839RoxFS1IpRPiVy7i45nXpdURkCA/s400/Azure_Portal_ACI_Demo_App.png" title="" width="400" /></a></div>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: 1.66667; margin-bottom: 0px; margin-top: calc(1.66667em); text-size-adjust: auto;">
Updating your container</h3>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; text-size-adjust: auto;">
No project is perfect the first time. Neither are your services you put inside a container. Updating your container is just a matter of tagging a new version and putting it live.</div>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
To make it easy for you I’ve provided a branch called “update” so you can go immediately started.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">git checkout update
docker build . -t aci-tutorial-app
docker run -p 8000:80 --rm --name aci_tutorial_webapp aci-tutorial-app
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
Now we just go to <a href="http://localhost:8000/books" rel="nofollow" target="_blank">localhost:8000/books</a> to verify our affiliation links are there.</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYNm7Dw53Qf2nNryWDYGeUGM2tnUxwGhkkHZ4KmMBwcAT0nfF6DlPBGL327LtlClSSpP753jlTadxoJ5qt5W692XDVoOajvSlvGjxAAWnG5rcd_cdxauckzPoNpu4qxnKvsIhbSg/s1600/ACI_Demo_App_books_v2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1440" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYNm7Dw53Qf2nNryWDYGeUGM2tnUxwGhkkHZ4KmMBwcAT0nfF6DlPBGL327LtlClSSpP753jlTadxoJ5qt5W692XDVoOajvSlvGjxAAWnG5rcd_cdxauckzPoNpu4qxnKvsIhbSg/s400/ACI_Demo_App_books_v2.png" width="400" /></a></div>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
Now that we’ve verified everything is working, it’s time to tag it again and push it upstream.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">docker tag aci-tutorial-app acidemomvp.azurecr.io/aci-tutorial-app:v2
docker push acidemomvp.azurecr.io/aci-tutorial-app:v2
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
It could be your session got timed out, the following message will give you more details.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">The push refers to repository [acidemomvp.azurecr.io/aci-tutorial-app]
7d6222784cfc: Preparing
135f6b00eec7: Preparing
29e829473f65: Preparing
5df56ca2422c: Preparing
0fe69bd96626: Preparing
4f65eb3ac611: Waiting
8a3436067bb2: Waiting
6443b41f72f9: Waiting
993df43bf684: Waiting
530e50cf94e4: Waiting
86700745f1ec: Waiting
a6f0d3e3e138: Waiting
550c61595337: Waiting
ab779a053abe: Waiting
cec8466f473c: Waiting
d45e3781d4b2: Waiting
8d8f451305fc: Waiting
e416a4904ee4: Waiting
2ec5c0a4cb57: Waiting
unauthorized: authentication required
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
To login again, the following statement will help you further.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">az acr login --name aciDemoMvp
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
This should give you a success statement.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">Login Succeeded
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
The moment authentication is again approved, you can now safely push your container upstream.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">docker push acidemomvp.azurecr.io/aci-tutorial-app:v2
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
Again a new checksum will be calculated and returned.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">The push refers to repository [acidemomvp.azurecr.io/aci-tutorial-app]
7d6222784cfc: Pushed
135f6b00eec7: Pushed
29e829473f65: Layer already exists
5df56ca2422c: Layer already exists
0fe69bd96626: Layer already exists
4f65eb3ac611: Layer already exists
8a3436067bb2: Layer already exists
6443b41f72f9: Layer already exists
993df43bf684: Layer already exists
530e50cf94e4: Layer already exists
86700745f1ec: Layer already exists
a6f0d3e3e138: Layer already exists
550c61595337: Layer already exists
ab779a053abe: Layer already exists
cec8466f473c: Layer already exists
d45e3781d4b2: Layer already exists
8d8f451305fc: Layer already exists
e416a4904ee4: Layer already exists
2ec5c0a4cb57: Layer already exists
v2: digest: sha256:68f34616e57313dfbb604e21e0085f044c10ab033ffdefe929947ef04d75717e size: 4285
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
Now it’s time to upgrade the container.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">az container create --resource-group aciDemoApp --name aci-tutorial-app --image acidemomvp.azurecr.io/aci-tutorial-app:v2 --cpu 1 --memory 1 --ip-address public --ports 80 --registry-password "0tXXLUN+/Ye+8RBotZRRst7OU+I=CteG"
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
Notice we used the same password as before, but this time we’re using<span class="Apple-converted-space"> </span><code style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0.08333em 0.1667em 0.1667em; white-space: pre-wrap;">acidemomvp.azurecr.io/aci-tutorial-app:v2</code>, our updated container tag.</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">{
"containers": [
{
"command": null,
"environmentVariables": [],
"image": "acidemomvp.azurecr.io/aci-tutorial-app:v1",
"instanceView": null,
"name": "aci-tutorial-app",
"ports": [
{
"port": 80,
"protocol": null
}
],
"resources": {
"limits": null,
"requests": {
"cpu": 1.0,
"memoryInGb": 1.0
}
},
"volumeMounts": null
}
],
"id": "/subscriptions/abcd1234-abcd-1234-abcd-123456abcdef/resourceGroups/aciDemoApp/providers/Microsoft.ContainerInstance/containerGroups/aci-tutorial-app",
"imageRegistryCredentials": [
{
"password": null,
"server": "acidemomvp.azurecr.io",
"username": "acidemomvp"
}
],
"instanceView": {
"events": [],
"state": "Pending"
},
"ipAddress": {
"ip": "40.68.171.88",
"ports": [
{
"port": 80,
"protocol": "TCP"
}
]
},
"location": "westeurope",
"name": "aci-tutorial-app",
"osType": "Linux",
"provisioningState": "Creating",
"resourceGroup": "aciDemoApp",
"restartPolicy": "Always",
"tags": null,
"type": "Microsoft.ContainerInstance/containerGroups",
"volumes": null
}
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
This means that your container is updated, using the same IP address as we had before. Point your browser to<span class="Apple-converted-space"> </span><a href="http://40.68.171.88/" style="box-sizing: border-box; color: #1a1a1a;">40.68.171.88</a><span class="Apple-converted-space"> </span>and see your updated application running as a container on<span class="Apple-converted-space"> </span><a href="https://azure.microsoft.com/" style="box-sizing: border-box; color: #1a1a1a;">Microsoft Azure</a>.</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj14IxWe06dAYWOJh0xUdqcCp5WM6fZl1pXKDwISZx4sdc4fkSxl7AOH7ykh4lp2V1JFejD88zqXM0xlpwIgDciBmBmy-2KLge4jB2DRCf7woeqomOwWKothY9gcKTEBDWeW4pCVQ/s1600/ACI_Demo_App.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Your updated application running in the cloud" border="0" data-original-height="900" data-original-width="1440" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj14IxWe06dAYWOJh0xUdqcCp5WM6fZl1pXKDwISZx4sdc4fkSxl7AOH7ykh4lp2V1JFejD88zqXM0xlpwIgDciBmBmy-2KLge4jB2DRCf7woeqomOwWKothY9gcKTEBDWeW4pCVQ/s400/ACI_Demo_App.png" title="" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfCA1WViYdQBUm1zXNTHM07hQdgHqdn8SSFCHzb4LOhyTV8zfkpCnfKyYJFUabPgMz2sOvWearxxA7KzE30XDsF6yCMDNPP_o5YlHu2zD2XmXt80TUWUH8t0zX1848amBhbL9pgQ/s1600/ACI_Demo_App_books_v2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Now with affiliation links" border="0" data-original-height="900" data-original-width="1440" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfCA1WViYdQBUm1zXNTHM07hQdgHqdn8SSFCHzb4LOhyTV8zfkpCnfKyYJFUabPgMz2sOvWearxxA7KzE30XDsF6yCMDNPP_o5YlHu2zD2XmXt80TUWUH8t0zX1848amBhbL9pgQ/s400/ACI_Demo_App_books_v2.png" title="" width="400" /></a></div>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: 1.66667; margin-bottom: 0px; margin-top: calc(1.66667em); text-size-adjust: auto;">
Destroy your container</h3>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">az group delete --name aciDemoApp
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
It will ask for your confirmation</div>
<pre style="background-color: #f0f0f0; border-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); overflow: hidden; padding: 1rem; text-size-adjust: auto; white-space: pre-wrap;"><code style="border-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.833333em); padding: 0px;">Are you sure you want to perform this operation? (y/n): y
</code></pre>
<h2 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: calc(1.16667em); line-height: 1.42857; margin-bottom: calc(1.66667em); margin-top: calc(2.85714em); text-size-adjust: auto;">
Next articles in the pipeline</h2>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
Now that we have learned how to get a basic Docker application deployed on<span class="Apple-converted-space"> </span><a href="https://azure.microsoft.com/" style="box-sizing: border-box; color: #1a1a1a;">Microsoft Azure</a>, let’s dig a little bit deeper in how we can fully utilise the services provided by Azure.</div>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
This are a few articles I’m working on, so come back regularly to learn how you can easily deploy applications on the cloud using<span class="Apple-converted-space"> </span><a href="https://www.docker.com/" style="box-sizing: border-box; color: #1a1a1a;">Docker</a><span class="Apple-converted-space"> </span>and<span class="Apple-converted-space"> </span><a href="https://azure.microsoft.com/" style="box-sizing: border-box; color: #1a1a1a;">Microsoft Azure</a>.</div>
<ul style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; list-style: none; margin: calc(1.66667em) auto 0px; padding-left: 2.2222rem; text-size-adjust: auto;">
<li style="box-sizing: border-box;">Storing data and files outside of your<span class="Apple-converted-space"> </span><a href="https://www.docker.com/" style="box-sizing: border-box; color: #1a1a1a;">Docker</a><span class="Apple-converted-space"> </span>containers</li>
<li style="box-sizing: border-box;">Deploying a distributed architecture on<span class="Apple-converted-space"> </span><a href="https://azure.microsoft.com/" style="box-sizing: border-box; color: #1a1a1a;">Microsoft Azure</a></li>
<li style="box-sizing: border-box;">Securing your applications with<span class="Apple-converted-space"> </span><a href="https://azure.microsoft.com/en-us/services/key-vault/" style="box-sizing: border-box; color: #1a1a1a;">Microsoft Azure Key Vault</a><span class="Apple-converted-space"> </span>and<span class="Apple-converted-space"> </span><a href="https://www.docker.com/" style="box-sizing: border-box; color: #1a1a1a;">Docker</a></li>
</ul>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 16px; margin-left: auto; margin-right: auto; margin-top: calc(1.66667em); text-size-adjust: auto;">
Please leave feedback and let me know if this tutorial was interesting and what you like to see in the future as well.</div>
M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com2tag:blogger.com,1999:blog-28215292.post-19617736731152028812017-06-07T18:30:00.000+02:002017-06-07T18:30:21.992+02:00VAT Validation now for PHP 7.1+<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-RM0Ucpbh31wxUJ5tGnkyYtoDZdU64RZn32Q3Ygz0bfot-YkdG2n4lL8x6TDz7Rzsuox7D9thqeXml3JjwLEo-FIaeln2pzrbIppvN7yUXB1QMWpvwd_8hoBvGDuAE_2YNjwmPg/s1600/IMG_8327.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="114" data-original-width="291" height="156" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-RM0Ucpbh31wxUJ5tGnkyYtoDZdU64RZn32Q3Ygz0bfot-YkdG2n4lL8x6TDz7Rzsuox7D9thqeXml3JjwLEo-FIaeln2pzrbIppvN7yUXB1QMWpvwd_8hoBvGDuAE_2YNjwmPg/s400/IMG_8327.PNG" width="400" /></a></div>
<br />
When I started my <a href="https://github.com/DragonBe/vies">European Commission (EC) VAT Information Exchange System (VIES)</a> project back in 2011, PHP 5.3 was the current version that has given us so much. Earlier that year <a href="http://php.net/eol.php">version 5.2 was announced End-of-Life</a> and everyone was excited about the new features in PHP coming with the 5.3.x releases.<br />
<br />
But fast-forwarding to today, PHP 7.1 is the latest stable release and <a href="http://php.net/supported-versions.php">PHP 5.6 only gets security fixes until the end of this year</a>. In the mean time several open-source projects like <a href="https://twitter.com/s_bergmann/status/694777369177927680">PHPUnit</a>, <a href="https://twitter.com/xdebug/status/808633143972556800">XDebug</a>, <a href="https://framework.zend.com/blog/2017-06-06-zf-php-7-1.html">Zend Framework</a>, <a href="https://twitter.com/taylorotwell/status/809767371774816256">Laravel</a>, <a href="https://magazine.joomla.org/issues/issue-feb-2016/item/2965-faster-safer-more-stable-joomla-and-php7">Joomla</a>, <a href="https://typo3.org/typo3-cms/roadmap/">TYPO3</a>, <a href="https://twitter.com/jasonwoosley_mg/status/870421429325516800">Magento</a> and <a href="https://twitter.com/fabpot/status/809743412715016192">Symfony</a> announced they stop development for PHP 5 versions and now only move forward with PHP 7.1 and higher.<br />
<br />
After seeing <a href="https://twitter.com/s_bergmann" rel="nofollow" target="_blank">Sebastian Bergmann</a>’s talk <a href="https://thephp.cc/dates/2017/05/php-tek/php-7-reality-check">PHP 7: Reality Check</a> I was empowered by his reasoning that it’s not worth putting support in outdated PHP versions and focus on the current and future versions that will make a difference in functionality, performance and security.<br />
<br />
For this reason I would like to announce that the <a href="https://github.com/DragonBe/vies">European Commission (EC) VAT Information Exchange System (VIES)</a> project will no longer support PHP 5 and uses PHP 7.1 features to ensure better security and application control.<br />
<br />
We’re going to follow the <a href="https://secure.php.net/supported-versions.php" rel="nofollow" target="_blank">release and support cycle of PHP</a> itself and will only offer security fixes on our 1.x branch. If you can’t wait to run our VIES service in your PHP 7.1 web application, you can go ahead and update directly through <a href="https://getcomposer.org/">Composer</a>.<br />
<br />
<pre><code>composer update dragonbe/vies
</code></pre>
<br />
If you’re starting a new project and you would like to add VAT validation you can install it easily with <a href="https://getcomposer.org/">Composer</a>.<br />
<br />
<pre><code>composer require dragonbe/vies
</code></pre>
<br />
As mentioned, I will only provide security fixes on the 1.x branch until the end of this year! If you’re already using this VIES project in your own projects, I <b>urge you to upgrade to PHP 7.1</b> to enjoy future features and updates.M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com0tag:blogger.com,1999:blog-28215292.post-21439628965049731952017-03-18T16:50:00.000+01:002017-03-18T16:50:36.115+01:00PHP 7 and Apache on macOS Sierra<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrukLT8bvcAE_RYXq-wscGqsyYbWN4H2abT7RyfUEp5_9jOpatTnLKXR-X-U572Gma3v_IbPn2r3PeP6ZpVFhz60N-RO7X9LHJjKS68o6pE7plo-RxnrYcR1NqE6LCxHBGUXFG5Q/s1600/macOS+Sierra+with+PHP+7.1+small.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrukLT8bvcAE_RYXq-wscGqsyYbWN4H2abT7RyfUEp5_9jOpatTnLKXR-X-U572Gma3v_IbPn2r3PeP6ZpVFhz60N-RO7X9LHJjKS68o6pE7plo-RxnrYcR1NqE6LCxHBGUXFG5Q/s400/macOS+Sierra+with+PHP+7.1+small.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">PHP 7.1.2 running on macOS Sierra</td></tr>
</tbody></table>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 15px; margin-left: auto; margin-right: auto;">
I posted several talks about compiling PHP from source, but everyone was trying to convince me that a package manager like <a href="https://brew.sh/" style="box-sizing: border-box; color: #1a1a1a;">Homebrew</a> was a more convenient way to install.</div>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 15px; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
The purpose of <a href="https://brew.sh/" style="box-sizing: border-box; color: #1a1a1a;">Homebrew</a> is simple: a package manager for macOS that will allow you to set up and install common packages easily and allows you to update frequently using simple commands.</div>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 15px; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
I used a clean installation of <a href="https://www.apple.com/macos/sierra/" style="box-sizing: border-box; color: #1a1a1a;">macOS Sierra</a> to ensure all steps could be recorded and tested. In most cases you already have done work on your Mac, so chances are you can skip a few steps in this tutorial.</div>
<h1 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: calc(1.2777777777777777em); letter-spacing: 0.5px; line-height: calc(1.3043478260869565); margin: calc(2.608695652173913em) 0px; text-transform: uppercase;">
APACHE AND PHP WITH HOMEBREW</h1>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 15px; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
I’ve made this according to the installation instructions given on <a href="https://getgrav.org/blog/macos-sierra-apache-multiple-php-versions" style="box-sizing: border-box; color: #1a1a1a;">GetGrav</a>.</div>
<h2 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: calc(1.1666666666666667em); line-height: calc(1.4285714285714286); margin-bottom: calc(1.6666666666666667em); margin-top: calc(2.857142857142857em);">
The installation procedures</h2>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 15px; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
These installation procedures will set up your <a href="https://www.apple.com/macos/sierra/" style="box-sizing: border-box; color: #1a1a1a;">macOS Sierra</a> with PHP 7.1 and Apache 2.4.</div>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: calc(1.6666666666666667); margin-bottom: 0px; margin-top: calc(1.6666666666666667em);">
Install Xcode command line tools (if not done yet)</h3>
<pre style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 15px; margin-left: auto; margin-right: auto; overflow: hidden; padding: 1rem; white-space: pre-wrap;"><code style="border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); padding: 0px;">xcode-select --install
</code></pre>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: calc(1.6666666666666667); margin-bottom: 0px; margin-top: calc(1.6666666666666667em);">
Install Homebrew</h3>
<pre style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 15px; margin-left: auto; margin-right: auto; overflow: hidden; padding: 1rem; white-space: pre-wrap;"><code style="border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); padding: 0px;">/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 15px; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
Set up for installation of PHP and Apache</div>
<pre style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 15px; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em); overflow: hidden; padding: 1rem; white-space: pre-wrap;"><code style="border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); padding: 0px;">brew tap homebrew/dupes
brew tap homebrew/versions
brew tap homebrew/homebrew-php
brew tap homebrew/apache
</code></pre>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: calc(1.6666666666666667); margin-bottom: 0px; margin-top: calc(1.6666666666666667em);">
Unload the provisioned Apache from macOS Sierra</h3>
<pre style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 15px; margin-left: auto; margin-right: auto; overflow: hidden; padding: 1rem; white-space: pre-wrap;"><code style="border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); padding: 0px;">sudo apachectl stop
sudo launchctl unload -w /System/Library/LaunchDaemons/org.apache.httpd.plist 2>/dev/null
</code></pre>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: calc(1.6666666666666667); margin-bottom: 0px; margin-top: calc(1.6666666666666667em);">
Install Homebrew Apache</h3>
<pre style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 15px; margin-left: auto; margin-right: auto; overflow: hidden; padding: 1rem; white-space: pre-wrap;"><code style="border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); padding: 0px;">brew install httpd24 --with-privileged-ports --with-http2
</code></pre>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: calc(1.6666666666666667); margin-bottom: 0px; margin-top: calc(1.6666666666666667em);">
Set up Apache for autostart at macOS Sierra (re)boot</h3>
<pre style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 15px; margin-left: auto; margin-right: auto; overflow: hidden; padding: 1rem; white-space: pre-wrap;"><code style="border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); padding: 0px;">sudo cp -v /usr/local/Cellar/httpd24/2.4.25/homebrew.mxcl.httpd24.plist /Library/LaunchDaemons
sudo chown -v root:wheel /Library/LaunchDaemons/homebrew.mxcl.httpd24.plist
sudo chmod -v 644 /Library/LaunchDaemons/homebrew.mxcl.httpd24.plist
sudo launchctl load /Library/LaunchDaemons/homebrew.mxcl.httpd24.plist
</code></pre>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: calc(1.6666666666666667); margin-bottom: 0px; margin-top: calc(1.6666666666666667em);">
Check to see Apache is running</h3>
<pre style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 15px; margin-left: auto; margin-right: auto; overflow: hidden; padding: 1rem; white-space: pre-wrap;"><code style="border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); padding: 0px;">ps -aef | grep httpd
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 15px; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
You should see something similar as output</div>
<pre style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 15px; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em); overflow: hidden; padding: 1rem; white-space: pre-wrap;"><code style="border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); padding: 0px;"> 0 23417 1 0 2:48PM ?? 0:00.06 /usr/local/opt/httpd24/bin/httpd -D FOREGROUND
1 23420 23417 0 2:48PM ?? 0:00.00 /usr/local/opt/httpd24/bin/httpd -D FOREGROUND
1 23421 23417 0 2:48PM ?? 0:00.00 /usr/local/opt/httpd24/bin/httpd -D FOREGROUND
1 23422 23417 0 2:48PM ?? 0:00.00 /usr/local/opt/httpd24/bin/httpd -D FOREGROUND
1 23423 23417 0 2:48PM ?? 0:00.00 /usr/local/opt/httpd24/bin/httpd -D FOREGROUND
1 23424 23417 0 2:48PM ?? 0:00.00 /usr/local/opt/httpd24/bin/httpd -D FOREGROUND
501 23428 403 0 2:48PM ttys000 0:00.00 grep httpd
</code></pre>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: calc(1.6666666666666667); margin-bottom: 0px; margin-top: calc(1.6666666666666667em);">
Uninstall previous versions of PHP</h3>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 15px; margin-left: auto; margin-right: auto;">
We assume you had PHP 7.0 installed</div>
<pre style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 15px; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em); overflow: hidden; padding: 1rem; white-space: pre-wrap;"><code style="border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); padding: 0px;">brew unlink php70
</code></pre>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: calc(1.6666666666666667); margin-bottom: 0px; margin-top: calc(1.6666666666666667em);">
Install latest PHP version (PHP 7.1.2 at the time of writing)</h3>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 15px; margin-left: auto; margin-right: auto;">
Time to install latest PHP with the apache web server</div>
<pre style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 15px; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em); overflow: hidden; padding: 1rem; white-space: pre-wrap;"><code style="border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); padding: 0px;">brew install php71 --with-httpd24
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 15px; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
<span style="box-sizing: border-box; font-weight: 600;">Don’t forget to set <code style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); font-weight: 500; padding: 0.08333em 0.1667em 0.1667em; white-space: pre-wrap;">date.timezone</code> in <code style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); font-weight: 500; padding: 0.08333em 0.1667em 0.1667em; white-space: pre-wrap;">/usr/local/etc/php/7.1/php.ini</code>!!!</span></div>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: calc(1.6666666666666667); margin-bottom: 0px; margin-top: calc(1.6666666666666667em);">
Configure Apache for PHP usage</h3>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 15px; margin-left: auto; margin-right: auto;">
Also make sure to set the following line in <code style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); padding: 0.08333em 0.1667em 0.1667em; white-space: pre-wrap;">/usr/local/etc/apache2/2.4/httpd.conf</code> (You might need to disable others):</div>
<pre style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 15px; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em); overflow: hidden; padding: 1rem; white-space: pre-wrap;"><code style="border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); padding: 0px;">LoadModule php7_module /usr/local/opt/php71/libexec/apache2/libphp7.so
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 15px; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
Also make sure you have set the following lines correctly:</div>
<pre style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 15px; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em); overflow: hidden; padding: 1rem; white-space: pre-wrap;"><code style="border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); padding: 0px;">#
# DirectoryIndex: sets the file that Apache will serve if a directory
# is requested.
#
<ifmodule dir_module="">
DirectoryIndex index.html index.php
</ifmodule>
<filesmatch php="">
SetHandler application/x-httpd-php
</filesmatch>
</code></pre>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: calc(1.6666666666666667); margin-bottom: 0px; margin-top: calc(1.6666666666666667em);">
Time to restart apache</h3>
<pre style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 15px; margin-left: auto; margin-right: auto; overflow: hidden; padding: 1rem; white-space: pre-wrap;"><code style="border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); padding: 0px;">sudo /usr/local/bin/apachectl -k restart
</code></pre>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: calc(1.6666666666666667); margin-bottom: 0px; margin-top: calc(1.6666666666666667em);">
Test your setup</h3>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 15px; margin-left: auto; margin-right: auto;">
Create a <code style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); padding: 0.08333em 0.1667em 0.1667em; white-space: pre-wrap;">phpinfo.php</code> in <code style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); padding: 0.08333em 0.1667em 0.1667em; white-space: pre-wrap;">/usr/local/var/www/htdocs</code> with the following contents:</div>
<pre style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; color: #1a1a1a; font-family: monospace, monospace; font-size: 15px; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em); overflow: hidden; padding: 1rem; white-space: pre-wrap;"><code style="border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); padding: 0px;"><?php phpinfo();
</code></pre>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 15px; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
You should see the famous PHP information page!</div>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 15px; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEja4opuktE3Bs2JCiJh5ZcA4QpbeNjZWU5ssmlPudJNpsOSV4eIcO7c9ejGzazQxVOiBh0hRo-oMYMAsyyV_UmBHMu_xRTzVACfpdH3RY8UW524IGHXnzf5QyBY-UGycRJtM282zw/s1600/macOS+Sierra+with+PHP+7.1+small.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEja4opuktE3Bs2JCiJh5ZcA4QpbeNjZWU5ssmlPudJNpsOSV4eIcO7c9ejGzazQxVOiBh0hRo-oMYMAsyyV_UmBHMu_xRTzVACfpdH3RY8UW524IGHXnzf5QyBY-UGycRJtM282zw/s400/macOS+Sierra+with+PHP+7.1+small.png" width="400" /></a></div>
<h3 style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 1em; line-height: calc(1.6666666666666667); margin-bottom: 0px; margin-top: calc(1.6666666666666667em);">
Next steps</h3>
<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 15px; margin-left: auto; margin-right: auto;">
Now you can set up your virtual hosts like you normally would do.</div>
M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com2tag:blogger.com,1999:blog-28215292.post-7811871070362136912016-12-17T00:58:00.001+01:002016-12-22T18:24:44.585+01:00Sessions in PHP 7.1 and Redis<div style="box-sizing: border-box; color: #1a1a1a; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: 15px; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEir5BnuVqHrMnyI49oulY45eEwVn0-WEU2qTuHUXGYIqzb3Kng-q7KNsavSc4RSkWvK6SB_4c67uPoWftL5q7ZASObfdP4pH0AwLWbszcHiPI9M79tkNn1OIWqhigxv-asPmcRlIg/s1600/IMG_8327.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEir5BnuVqHrMnyI49oulY45eEwVn0-WEU2qTuHUXGYIqzb3Kng-q7KNsavSc4RSkWvK6SB_4c67uPoWftL5q7ZASObfdP4pH0AwLWbszcHiPI9M79tkNn1OIWqhigxv-asPmcRlIg/s1600/IMG_8327.PNG" /></a></div>
<div style="box-sizing: border-box; font-family: NittiGrotesk, Keyboard, sans-serif; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
In case you have missed it, <a href="http://php.net/archive/2016.php#id2016-12-01-3" style="box-sizing: border-box; color: #1a1a1a;">PHP 7.1.0 has been released recently</a>. Now you can’t wait to upgrade your servers to the latest and greatest PHP version ever. But hold that thought a second…</div>
<div style="box-sizing: border-box; font-family: NittiGrotesk, Keyboard, sans-serif; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
With <a href="http://www.slideshare.net/DragonBe/getting-hands-dirty-with-php7" style="box-sizing: border-box; color: #1a1a1a;">PHP 7 lots of things have changed</a> underneath the hood. But these changed features can also put unexpected challenges on your path.</div>
<h2 style="box-sizing: border-box; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: calc(1.1666666666666667em); line-height: calc(1.4285714285714286); margin-bottom: calc(1.6666666666666667em); margin-top: calc(2.857142857142857em);">
Our challenge</h2>
<div style="box-sizing: border-box; font-family: NittiGrotesk, Keyboard, sans-serif; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
One of these challenges that we faced was getting PHP 7.1 to play nice storing sessions in our <a href="https://redis.io/" style="box-sizing: border-box; color: #1a1a1a;">Redis</a> storage. In order to store sessions in Redis, we needed to install the <a href="https://pecl.php.net/package/redis" style="box-sizing: border-box; color: #1a1a1a;">Redis PHP extension</a> that not only provides <a href="https://github.com/phpredis/phpredis/#classes-and-methods" style="box-sizing: border-box; color: #1a1a1a;">PHP functions for Redis</a>, but also installs the <a href="https://github.com/phpredis/phpredis/#php-session-handler" style="box-sizing: border-box; color: #1a1a1a;">PHP session handler for Redis</a>.</div>
<div style="box-sizing: border-box; font-family: NittiGrotesk, Keyboard, sans-serif; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
Because we upgraded our servers to PHP 7.1, we were looking to use the latest provided version for this Redis extension: redis-3.1.0. Once installed, we bumped against a nasty problem.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1dE19PjAkZ1xN3L52O5NCcxcpDtOyNh9bm5W8xa9oATqtYVaUsyNaFqNUzeyCU6F_LuWJevQuvzqX-JQKrmvtbGzlWDQbVbnWwIiLu_KgGGvqPpuW29OHNPVAkrcQNGs8t2dxqw/s1600/Screenshot+2016-12-15+18.58.46.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="113" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1dE19PjAkZ1xN3L52O5NCcxcpDtOyNh9bm5W8xa9oATqtYVaUsyNaFqNUzeyCU6F_LuWJevQuvzqX-JQKrmvtbGzlWDQbVbnWwIiLu_KgGGvqPpuW29OHNPVAkrcQNGs8t2dxqw/s400/Screenshot+2016-12-15+18.58.46.png" width="400" /></a></div>
<pre style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: monospace, monospace; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em); overflow: hidden; padding: 1rem; white-space: pre-wrap;"><code style="border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); padding: 0px;">Warning: session_start(): Failed to read session data: redis (path: tcp://127.0.0.1:6379)
</code></pre>
<div style="box-sizing: border-box; font-family: NittiGrotesk, Keyboard, sans-serif; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
Searching the internet for this error, we didn’t got many hits that could point us into a direction of a solution. </div>
<div style="box-sizing: border-box; font-family: NittiGrotesk, Keyboard, sans-serif; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
We came up with this very basic PHP code snippet that could reproduce the error in a clean, stand-alone way. Since we used a framework, we wanted to make sure the problem was in PHP and not related to the choice of our PHP framework.</div>
<pre style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: monospace, monospace; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em); overflow: hidden; padding: 1rem; white-space: pre-wrap;"><code style="border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); padding: 0px;"><?php
ini_set('session.save_handler', 'redis');
ini_set(
'session.save_path', 'tcp://devcache1:6379'
);
session_name('FOOBAR');
session_start();
echo nl2br(
'<pre>' . session_save_path() . '</pre>' . PHP_EOL
);
echo nl2br(
'Running PHP version: ' . phpversion() . PHP_EOL
);
if (!array_key_exists('visit', $_SESSION)) {
$_SESSION['visit'] = 0;
}
$_SESSION['visit']++;
echo nl2br(
'You have been here ' . $_SESSION['visit'] . ' times.'
);
</code></pre>
<div style="box-sizing: border-box; font-family: NittiGrotesk, Keyboard, sans-serif; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
To give us some room to try things out, we decided to use <a href="https://www.docker.com/" style="box-sizing: border-box; color: #1a1a1a;">Docker</a> to create containers for us to try things out while searching for a solution. Find our basic setup from my <a href="https://github.com/DragonBe/docker-php-redis-example" style="box-sizing: border-box; color: #1a1a1a;">GitHub repository</a>.</div>
<pre style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: monospace, monospace; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em); overflow: hidden; padding: 1rem; white-space: pre-wrap;"><code style="border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); padding: 0px;">cd /path/to/workspace
git clone https://github.com/DragonBe/docker-php-redis-example.git
cd docker-php-redis-example/
</code></pre>
<div style="box-sizing: border-box; font-family: NittiGrotesk, Keyboard, sans-serif; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
We’ve added a <code style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); padding: 0.08333em 0.1667em 0.1667em; white-space: pre-wrap;">docker-compose.yml</code> to get started quickly using <a href="https://docs.docker.com/compose/overview/" style="box-sizing: border-box; color: #1a1a1a;">Docker Compose</a>.</div>
<pre style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: monospace, monospace; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em); overflow: hidden; padding: 1rem; white-space: pre-wrap;"><code style="border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); padding: 0px;">docker-compose up
</code></pre>
<div style="box-sizing: border-box; font-family: NittiGrotesk, Keyboard, sans-serif; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
This command will launch the different containers for PHP 5.6, 7.0 and 7.1 including a single Redis instance.</div>
<div style="box-sizing: border-box; font-family: NittiGrotesk, Keyboard, sans-serif; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
In the following <a href="https://youtu.be/cXvH2LLWylg" style="box-sizing: border-box; color: #1a1a1a;">YouTube video</a> you can see what we experienced on our side.</div>
<div style="box-sizing: border-box; font-family: NittiGrotesk, Keyboard, sans-serif; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
<a href="https://youtu.be/cXvH2LLWylg" rel="nofollow" target="_blank"><img alt="PHP7, Redis extension and Docker" src="https://i.ytimg.com/vi/cXvH2LLWylg/0.jpg" style="border: 0px; box-sizing: border-box; max-width: 100%; vertical-align: top;" title="PHP7, Redis extension and Docker" /></a><span id="goog_1434593473"></span><span id="goog_1434593474"></span><a href="https://draft.blogger.com/"></a></div>
<div style="box-sizing: border-box; font-family: NittiGrotesk, Keyboard, sans-serif; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
The redis PHP session handler worked perfect for PHP 5.6, failed with Segmentation faults on PHP 7.0 and wasn’t able to initialise a new session on PHP 7.1. Remarkable was that once we started a session on PHP 5.6, the session handler was having no issues updating this existing session on PHP 7.1.</div>
<h2 style="box-sizing: border-box; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: calc(1.1666666666666667em); line-height: calc(1.4285714285714286); margin-bottom: calc(1.6666666666666667em); margin-top: calc(2.857142857142857em);">
Our solution</h2>
<div style="box-sizing: border-box; font-family: NittiGrotesk, Keyboard, sans-serif; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
So we figured out there must be something broken with the update in the redis extension. Looking at the <a href="https://pecl.php.net/package-changelog.php?package=redis&release=3.1.0" style="box-sizing: border-box; color: #1a1a1a;">changelog</a> we couldn’t directly spot a problem on how sessions are instantiated. Searching the internet we came to a lot of mentioning of <code style="background-color: #f0f0f0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; box-sizing: border-box; font-family: NittiPro, Keyboard, monospace; font-size: calc(0.8333333333333334em); padding: 0.08333em 0.1667em 0.1667em; white-space: pre-wrap;">session_regenerate_id()</code>, but this was not affected in our situation.</div>
<div style="box-sizing: border-box; font-family: NittiGrotesk, Keyboard, sans-serif; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
In one of the comments someone mentioned that a similar failure started appearing after upgrading from v3.0.0 to v3.1.0. That sparked our interest. We downgraded our redis extension to version 3.0.0 and tried again.</div>
<div style="box-sizing: border-box; font-family: NittiGrotesk, Keyboard, sans-serif; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
Hooray!!! Our session creation was now working on PHP 7.1, so mission accomplished. Now we needed to agree on taking the unfixed issues between redis-3.0.0 and redis-3.1.0 as compromise. Since the earlier mentioned changelog didn’t contain issues that directly could have an effect on our use cases for Redis it was easy to agree.</div>
<div style="box-sizing: border-box; font-family: NittiGrotesk, Keyboard, sans-serif; margin-left: auto; margin-right: auto; margin-top: calc(1.6666666666666667em);">
Now we’re enjoying running our web applications on PHP 7.1.0 while our sessions are handled through Redis. And we hope by sharing this experience, you too can enjoy running your PHP application on the latest version: PHP 7.1.<br />
<h2 style="box-sizing: border-box; font-family: NittiGrotesk, Keyboard, sans-serif; font-size: calc(1.1666666666666667em); line-height: calc(1.4285714285714286); margin-bottom: calc(1.6666666666666667em); margin-top: calc(2.857142857142857em);">
<a href="https://draft.blogger.com/null" name="update-20161222">Update 2016-12-22!!!</a></h2>
Today I received a tweet that there's an update available in the form of <a href="https://github.com/phpredis/phpredis/releases/tag/3.1.1RC1" rel="nofollow" target="_blank">redis-3.1.1RC1</a>. Go check out my <a href="https://github.com/DragonBe/docker-php-redis-example/tree/redis-update" rel="nofollow" target="_blank">github branch</a> to see how to implement it with <a href="https://www.docker.com/" rel="nofollow" target="_blank">Docker</a>.<br />
<br />
<blockquote class="twitter-tweet" data-lang="en">
<div dir="ltr" lang="en">
<a href="https://twitter.com/hollodotme">@hollodotme</a> <a href="https://twitter.com/DragonBe">@DragonBe</a> Should be fixed in 3.1.1. Tagged on github, pecl to follow shortly (<a href="https://t.co/hC2KOaMKYI">https://t.co/hC2KOaMKYI</a>)</div>
— Michael Grunder (@grumi78) <a href="https://twitter.com/grumi78/status/811734440573485056">December 22, 2016</a></blockquote>
<script async="" charset="utf-8" src="//platform.twitter.com/widgets.js"></script><br />
<br />
This fix also solves the issue I displayed for PHP 7.0. You should be good to go and implement it on your PHP 7 installations.</div>
</div>
M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com1tag:blogger.com,1999:blog-28215292.post-83755905241967451252016-09-26T14:51:00.000+02:002016-09-26T14:51:01.009+02:00PHP 7 on macOS Sierra<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVv4KNBgfX4JzwDFDOfvkEroeDfHx_wKGhpBHWVEIbuEl3-XfX3kb4soawCKyhnYRPKbh7QBtK1sbps8EgfeL5U9AdUhMjgrIk8eXd_Oen4jKyd3fXzp7OoThICO7s_TM4G_2M6A/s1600/macOS-Sierra.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVv4KNBgfX4JzwDFDOfvkEroeDfHx_wKGhpBHWVEIbuEl3-XfX3kb4soawCKyhnYRPKbh7QBtK1sbps8EgfeL5U9AdUhMjgrIk8eXd_Oen4jKyd3fXzp7OoThICO7s_TM4G_2M6A/s400/macOS-Sierra.jpg" width="400" /></a></div>
<br />
<h2>
PHP 7 on macOS Sierra</h2>
Apple has released the latest version of their OS X operating system to the broad public and many have already upgraded their mac devices. But as it goes with each release, Apple likes to do things a bit different making it quite challenging for PHP developers to stay current with the latest PHP version (or other versions).<br />
<br />
This version of mac OS (11.12) comes pre-installed with PHP 5.6.24.<br />
<br />
<code>
PHP 5.6.24 (cli) (built: Aug 8 2016 16:58:37)<br />
Copyright (c) 1997-2016 The PHP Group<br />
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies<br />
</code>
<br />
<br />
Good for Apple, but this version reaches <a href="http://php.net/supported-versions.php" rel="nofollow" target="_blank">end-of-life support by the end of this year</a>, so it would be great if you could upgrade to PHP 7.0 or even play with the latest PHP 7.1 release candidates.<br />
<br />
Of course you can always turn to Homebrew, XAMMP or whatever package manager you use for easy installations, but taking the compiling path is just as complicated. The failure is equal in most situations.<br />
<br />
Configuring PHP on macOS Sierra triggers the following error:<br />
<br />
<code><br />
apxs:Error: /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.12.xctoolchain/usr/local/bin/apr-1-config not found!.<br />
configure: error: Aborting<br />
</code><br />
<br />
In this version of Apple's OS the <a href="https://apr.apache.org/" rel="nofollow" target="_blank">Apache Portable Runtime</a> was not included. You need to download it and compile it yourself.<br />
<br />
<code>
wget http://apache.proserve.nl//apr/apr-1.5.2.tar.bz2<br />
wget http://apache.hippo.nl//apr/apr-util-1.5.4.tar.bz2<br />
</code><br />
<br />
Check the checksums!<br />
<br />
<code>
tar -xjf apr-1.5.2.tar.bz2<br />
tar -xjf apr-util-1.5.4.tar.bz2<br />
<br />
cd apr-1.5.2/<br />
./configure<br />
make<br />
make install<br />
<br />
cd ../apr-util-1.5.4/<br />
./configure --with-apr=/usr/local/apr<br />
make<br />
make install<br />
<br />
sudo mkdir -p /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.12.xctoolchain/usr/local/bin/<br />
sudo ln -s /usr/local/apr/bin/apu-1-config /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.12.xctoolchain/usr/local/bin/apu-1-config<br />
sudo ln -s /usr/local/apr/bin/apr-1-config /Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.12.xctoolchain/usr/local/bin/apr-1-config<br />
</code><br />
<br />
Now you can hapily compile and run the latest PHP version on the latest OS from Apple. See my previous article <a href="http://www.dragonbe.com/2016/07/compile-php-7-on-mac-os-x-1011-el.html" target="_blank">Compile PHP 7 on Mac OS X 10.11 "El Capitain"</a> for instructions.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuvH4bJmgfNEEeekaynKJivs7UHJ5rkuXAaw124TkxKj5gUVUgsDaXkU4WA9K3xyqaeQht7qjbSVJ7TYKVWh9-CnsoL7ZgteE1jBZspoAdEAP-foHwWcWHgDdQNG3Oah1X4qVn4w/s1600/Screenshot+2016-09-26+14.33.41.png" imageanchor="1"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuvH4bJmgfNEEeekaynKJivs7UHJ5rkuXAaw124TkxKj5gUVUgsDaXkU4WA9K3xyqaeQht7qjbSVJ7TYKVWh9-CnsoL7ZgteE1jBZspoAdEAP-foHwWcWHgDdQNG3Oah1X4qVn4w/s320/Screenshot+2016-09-26+14.33.41.png" width="640" /></a></div>
<br />
Happy PHP-ing!<br />
<br />M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com0tag:blogger.com,1999:blog-28215292.post-57980762598559451402016-07-19T14:00:00.000+02:002016-07-19T14:21:20.046+02:00Compile PHP 7 on Mac OS X 10.11 "El Capitain"<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYQraabosaKnG4bBkEZufVXRV818YelIfpHejEFHDJTAQgOqWktSP6Z4aUSvuqkq3L140o_irZUbsM9UPqHnNo8rnC6iiROq7-NGnHtV-jaXIYLdU4X-KQ7IMTBcs70c2hRuNy4g/s1600/Screenshot+2016-07-19+12.16.01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYQraabosaKnG4bBkEZufVXRV818YelIfpHejEFHDJTAQgOqWktSP6Z4aUSvuqkq3L140o_irZUbsM9UPqHnNo8rnC6iiROq7-NGnHtV-jaXIYLdU4X-KQ7IMTBcs70c2hRuNy4g/s1600/Screenshot+2016-07-19+12.16.01.png" /></a></div>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
<br /></div>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
Apple has made a numerous changes to the way <a href="http://www.apple.com/osx/" style="-webkit-print-color-adjust: exact; color: #0069d6;">OS X (10.11) "El Capitain"</a> uses open source elements like PHP and OpenSSL. Compiling PHP from source requires a bit more modifications.</div>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
This article is a follow-up on my previous post <strong style="-webkit-print-color-adjust: exact;"><a href="http://www.dragonbe.com/2015/12/installing-php-7-with-xdebug-apache-and.html" style="-webkit-print-color-adjust: exact; color: #0069d6;">Installing PHP 7 with XDebug, Apache and MySQL on OS X Yosemite</a></strong></div>
<h2 style="-webkit-print-color-adjust: exact; background-color: white; color: #404040; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 24px; line-height: 36px; margin: 0px; padding: 0px;">
OpenSSL</h2>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
Get the latest OpenSSL from <a href="https://openssl.org/" style="-webkit-print-color-adjust: exact; color: #0069d6;">openssl.org</a> and unpack it so you can work with the sources.</div>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
Then just execute:</div>
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;">./Configure shared darwin64-x86_64-cc
make depend
make
sudo make install
</code></pre>
<h2 style="-webkit-print-color-adjust: exact; background-color: white; color: #404040; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 24px; line-height: 36px; margin: 0px; padding: 0px;">
PHP 7</h2>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
Download the latest PHP 7 source code from php.net/download and unpack it in a temporarily directory, I like to use /tmp.</div>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
My configure command arguments:</div>
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;">./configure \
--prefix=/opt/php7 \
--enable-cli \
--enable-mbstring \
--enable-gd-native-ttf \
--enable-gd-jis-conv \
--enable-sockets \
--enable-exif \
--enable-ftp \
--enable-intl \
--enable-soap \
--enable-zip \
--with-apxs2 \
--with-iconv=/usr \
--with-config-file-path=/etc/php7 \
--with-config-file-scan-dir=/etc/php7/ext \
--with-libxml-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/ \
--with-openssl=/usr/local/ssl \
--with-curl \
--with-gd \
--with-libedit \
--with-mcrypt=/usr/local/bin \
--with-mysqli \
--with-zlib \
--with-pdo-mysql \
--with-mysql-sock=/tmp/mysql.sock
</code></pre>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
This gives me most of the modules and extensions I require for doing my PHP work. For concrete situations I prefer to use virtual machines or Docker containers to mimic the production environment as much as possible, but for small work it's easy to have it running natively on my local machine.</div>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
<strong style="-webkit-print-color-adjust: exact;">WARNING:</strong> Compile OpenSSL instead of using the build-in SSL as it's not compatible!</div>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
Edit PHP's <code style="-webkit-print-color-adjust: exact; background-color: #fee9cc; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; padding: 1px 3px;">Makefile</code> and find the line that begins with <code style="-webkit-print-color-adjust: exact; background-color: #fee9cc; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; padding: 1px 3px;">EXTRA_LIBS</code>. In this line, replace the following references <code style="-webkit-print-color-adjust: exact; background-color: #fee9cc; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; padding: 1px 3px;">-lcrypto</code> with <code style="-webkit-print-color-adjust: exact; background-color: #fee9cc; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; padding: 1px 3px;">/usr/local/ssl/lib/libcrypto.dylib</code> and <code style="-webkit-print-color-adjust: exact; background-color: #fee9cc; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; padding: 1px 3px;">-lssl</code> with <code style="-webkit-print-color-adjust: exact; background-color: #fee9cc; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; padding: 1px 3px;">/usr/local/ssl/lib/libssl.dylib</code>or where you have installed the latest OpenSSL library.</div>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
A convenient way is to use <code style="-webkit-print-color-adjust: exact; background-color: #fee9cc; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; padding: 1px 3px;">vi</code> and use <code style="-webkit-print-color-adjust: exact; background-color: #fee9cc; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; padding: 1px 3px;">:s/\-lcrypto/\usr\/local\/ssl\/lib\/libcrypto.dylib/g</code> to immediately replace all instances of <code style="-webkit-print-color-adjust: exact; background-color: #fee9cc; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; padding: 1px 3px;">-lcrypto</code> in the line. Do the same for <code style="-webkit-print-color-adjust: exact; background-color: #fee9cc; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; padding: 1px 3px;">-lssl</code> as well.</div>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
Once done, just execute <code style="-webkit-print-color-adjust: exact; background-color: #fee9cc; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; padding: 1px 3px;">make</code>, <code style="-webkit-print-color-adjust: exact; background-color: #fee9cc; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; padding: 1px 3px;">make test</code> and <code style="-webkit-print-color-adjust: exact; background-color: #fee9cc; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; padding: 1px 3px;">sudo make install</code> to install the latest PHP 7 version on your MacBook.</div>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
You might want to replace the build-in php with your new compiled version of PHP.</div>
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;">cd /usr/bin
sudo mv php php-orig
sudo ln -sf /opt/php7/bin/php php
</code></pre>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
When you execute <code style="-webkit-print-color-adjust: exact; background-color: #fee9cc; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; padding: 1px 3px;">php -v</code> you should see something like the following:</div>
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;">PHP 7.0.8 (cli) (built: Jul 19 2016 11:36:18) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
with Xdebug v2.4.0RC2, Copyright (c) 2002-2015, by Derick Rethans
</code></pre>
<h2 style="-webkit-print-color-adjust: exact; background-color: white; color: #404040; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 24px; line-height: 36px; margin: 0px; padding: 0px;">
Apache</h2>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
It's nice to have PHP on command line, but you might want to have it run in your apache configuration as well.</div>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
If you look at the output of "make install" you will see the line:</div>
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;">[activating module `php7' in /private/etc/apache2/httpd.conf]
</code></pre>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
This means PHP has modified your apache configuration and included the php7 module, you only need to activate it.</div>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
In <code style="-webkit-print-color-adjust: exact; background-color: #fee9cc; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; padding: 1px 3px;">/etc/apache/httpd.conf</code> find the following line:</div>
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;">LoadModule php5_module libexec/apache2/libphp5.so
</code></pre>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
And comment it out, as we're no longer use php 5, like this:</div>
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;">#LoadModule php5_module libexec/apache2/libphp5.so
</code></pre>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
Locate the line:</div>
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;">#LoadModule php7_module libexec/apache2/libphp7.so
</code></pre>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
And remove the comment hash (#) in front of it</div>
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;">LoadModule php7_module libexec/apache2/libphp7.so
</code></pre>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
Restart apache with <code style="-webkit-print-color-adjust: exact; background-color: #fee9cc; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; padding: 1px 3px;">sudo /usr/sbin/apachectl restart</code></div>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
Now put the following file (<code style="-webkit-print-color-adjust: exact; background-color: #fee9cc; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; padding: 1px 3px;">info.php</code>) in your document root (see <code style="-webkit-print-color-adjust: exact; background-color: #fee9cc; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; padding: 1px 3px;">/etc/apache/httpd.conf</code> where this is)</div>
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;">>?php phpinfo();
</code></pre>
<div style="-webkit-print-color-adjust: exact; background-color: white; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; margin-bottom: 9px; padding: 0px;">
And point your browser to that file on your local machine, in my case it is <a href="http://localhost/info.php" style="-webkit-print-color-adjust: exact; color: #0069d6;">http://localhost/info.php</a>.</div>
</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6bC2eqHTuT4en68AcxgXecWxwclHSWCVhrq3jrL7CZbg3bPA3fXJ1mbJH5q5qiJo5WrxznMPulq3l5GsyDCboPfIz7q2l9Mu6ehBYYXL2JozEQnEcIcx0XpXaFfjUl4TcahUIng/s1600/Screenshot+2016-07-19+11.57.29.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6bC2eqHTuT4en68AcxgXecWxwclHSWCVhrq3jrL7CZbg3bPA3fXJ1mbJH5q5qiJo5WrxznMPulq3l5GsyDCboPfIz7q2l9Mu6ehBYYXL2JozEQnEcIcx0XpXaFfjUl4TcahUIng/s400/Screenshot+2016-07-19+11.57.29.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">PHP 7.0.8 running on "El Capitain"</td></tr>
</tbody></table>
<br />
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<span style="background-color: white; color: #737373; font-family: "helvetica neue" , "helvetica" , "hiragino sans gb" , "arial" , sans-serif; font-size: 13px;">You're now ready to unleash the PHP7 power! Have fun and let me know in the comments if it worked out for you. If not, let's work together how we can solve the issue.</span></div>
M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com0tag:blogger.com,1999:blog-28215292.post-27317294017751893502016-06-01T09:00:00.000+02:002016-06-01T09:00:08.857+02:00PHPSrbija Conference 2016 review<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTEaOzHC0f8-z4MidRGhxeGU5PiySdd5SrcEifi5T4Nxn8Qu211B4oqKwVFclnJt3iwKHNg0XjwPr2niBMtR3Tl4iROjA5gIIZyp5I_sjKRd_LTlRJQJrnz6SHtPuARsCrOylEcQ/s1600/PHPSrbijaConference2016-Logo.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="142" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTEaOzHC0f8-z4MidRGhxeGU5PiySdd5SrcEifi5T4Nxn8Qu211B4oqKwVFclnJt3iwKHNg0XjwPr2niBMtR3Tl4iROjA5gIIZyp5I_sjKRd_LTlRJQJrnz6SHtPuARsCrOylEcQ/s320/PHPSrbijaConference2016-Logo.png" width="320" /></a></div>
This past weekend I was invited to speak at <a href="http://conf2016.phpsrbija.rs/" rel="nofollow" target="_blank">PHP Srbija Conference 2016</a> which was held in Belgrade, the capital of Serbia in the south-east of Europe.<br />
<br />
I feared that my departure from Brussels Airport was going to take up a lot of time since the terrorist bombing on March 22, but going through the additional security measures went very smoothly.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="margin-left: auto; margin-right: auto;"><a href="https://www.flickr.com/photos/dragonbe/26655091573/in/datetaken-public/" rel="nofollow" target="_blank"><img border="0" height="320" src="https://c2.staticflickr.com/8/7422/26655091573_fc229aabfc.jpg" width="320" /></a></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><a href="https://www.flickr.com/photos/dragonbe/26655091573/in/datetaken-public/" rel="nofollow" target="_blank">Arrived at Brussels Airport well ahead of departure time for #phpsrbija</a></td></tr>
</tbody></table>
So, I ended up in "the Loft" business lounge on terminal A where I could catch up on some email and do some work before my flight left for Zurich.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="margin-left: auto; margin-right: auto;"><a href="https://www.flickr.com/photos/dragonbe/26655711033/in/datetaken-public/" rel="nofollow" target="_blank"><img border="0" height="320" src="https://c2.staticflickr.com/8/7293/26655711033_c6a543f337.jpg" width="320" /></a></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><a href="https://www.flickr.com/photos/dragonbe/26655711033/in/datetaken-public/" rel="nofollow" target="_blank">Made it to “the Loft” lounge at Brussels Airport. Let’s get some work done! #IWorkAnywhere #DigitalNomad</a></td></tr>
</tbody></table>
This <a href="http://www.staralliance.com/" rel="nofollow" target="_blank">StarAlliance</a> business lounge offers soups, bread and hot snacks along with a variety of drinks. So while waiting for your flight you can relax in the very comfortable sofa's (see picture), have a desk-like table for meals or work, use the sleeping pods or take a shower. I decided to have my coffee and a warm snack before take-off.<br />
<br />
At the gate I got a pleasant surprise as I was upgraded to business class, making my trip to Zurich very comfortable.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://c2.staticflickr.com/8/7611/26658045173_f61f7b5243.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://c2.staticflickr.com/8/7611/26658045173_f61f7b5243.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Just got upgraded to @FlySWISS Business Class! W00t! #travelmagic #phpsrb2016</td></tr>
</tbody></table>
The flight from BRU to ZRH was quick and uneventful. Making the connection in Zurich was without stress as my flight to Belgrade was delayed. But Zurich is a very nice airport with lots of shops and bars, so instead of heading to the business lounge I ended up wondering around from shop to shop.<br />
<br />
At my arrival at Nikola Tesla Airport Belgrade I was welcomed by <a href="https://twitter.com/komita1981" rel="nofollow" target="_blank">Milan Popović</a>, one of the 3 organizers of the conference. Milan is a very passionate guy who made <a href="http://phpsrbija.rs/" rel="nofollow" target="_blank">PHP Srbija</a> to what it is today.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="margin-left: auto; margin-right: auto;"><a href="https://twitter.com/DragonBe/status/735927860171571200" rel="nofollow" target="_blank"><img border="0" height="320" src="https://pbs.twimg.com/media/CjaKfSxWgAAybz_.jpg" width="320" /></a></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><a href="https://twitter.com/DragonBe/status/735927860171571200" rel="nofollow" target="_blank">Awesome reception by @komita1981 as a great start for #phpsrb2016</a></td></tr>
</tbody></table>
Before we got to the hotel, we first went for dinner. The other two organizers <a href="https://twitter.com/AcoGagic" rel="nofollow" target="_blank">Aco Gagic</a> and <a href="https://twitter.com/nikolaposa" rel="nofollow" target="_blank">Nikola Poša</a>, a couple of volunteers, <a href="https://twitter.com/philsturgeon" rel="nofollow" target="_blank">Phil Sturgeon</a> and <a href="https://twitter.com/grmpyprogrammer" rel="nofollow" target="_blank">Chris Hartjes</a> were already there and had completed their meals. Milan and I joined the table and got extras. The food was awesome and made me forget I had traveled the bigger part of the day. That night, I slept immediately after we arrived at the hotel.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="margin-left: auto; margin-right: auto;"><a href="https://twitter.com/PHPSrbija/status/735911665292693504" rel="nofollow" target="_blank"><img border="0" height="180" src="https://pbs.twimg.com/media/CjZ7uI9WEAALZND.jpg" width="320" /></a></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><a href="https://twitter.com/PHPSrbija/status/735911665292693504" rel="nofollow" target="_blank">It's pre #phpsrb16 with @grmpyprogrammer @philsturgeon @DragonBe @nikolaposa @komita1981 @AcoGagic @LDusan</a></td></tr>
</tbody></table>
<br />
The day before the conference, Milan and Nikola took us on a tour at Belgrade Fortress, a beautiful piece of European history that is kept well preserved against the evils of time. If you visit Belgrade, you should visit this place, with perfect view over the Sava and Danube as it was build at their juncture. The visit was followed by a "small" lunch offered by the crew where we catched up with my good friend and fellow ninja turtle <a href="https://twitter.com/rdohms" rel="nofollow" target="_blank">Rafael Dohms</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="margin-left: auto; margin-right: auto;"><a href="https://www.flickr.com/photos/dragonbe/27283472095/in/datetaken-public/" rel="nofollow" target="_blank"><img border="0" height="320" src="https://c2.staticflickr.com/8/7334/27283472095_7ab12139e6.jpg" width="320" /></a></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><a href="https://www.flickr.com/photos/dragonbe/27283472095/in/datetaken-public/" rel="nofollow" target="_blank">Lunch time! #phpsrb2016</a></td></tr>
</tbody></table>
In the evening we were joined by <a href="https://twitter.com/CiaranMcNulty" rel="nofollow" target="_blank">Ciaran McNulty</a> when we went out for drinks and food. I've come to realize that "lots of meat" is just a simple meal in Serbia.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWRFBERfY57VAHJZJcE1mOdeEqHosH1CRCOkGOkfIGowC00S7iLrMhGPX52d-EzcKLj8eGcBsoyE32HAEsweeaMpQtrhyphenhyphenaI5U7Na6RTqiU_vAA7LvE37gv6C192YWK1iF-UNKx6Q/s1600/IMG_3222.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWRFBERfY57VAHJZJcE1mOdeEqHosH1CRCOkGOkfIGowC00S7iLrMhGPX52d-EzcKLj8eGcBsoyE32HAEsweeaMpQtrhyphenhyphenaI5U7Na6RTqiU_vAA7LvE37gv6C192YWK1iF-UNKx6Q/s320/IMG_3222.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Just a bit of meat</td></tr>
</tbody></table>
<br />
Conference Day 1! <a href="https://twitter.com/grmpyprogrammer" rel="nofollow" target="_blank">Chris Hartjes</a> was opening keynote and presented his best talk I've seen so far. Was it because of the great food or the warm welcome of the Serbian community, I leave that up to your immagination, but Chris flawlessly presented his keynote talk "An oral history of how I became Grumpy". The rest of the day was filled by <a href="https://twitter.com/s_bergmann" rel="nofollow" target="_blank">Sebastian Bergmann</a>, <a href="https://twitter.com/rdohms" rel="nofollow" target="_blank">Rafael Dohms</a>, <a href="https://twitter.com/CiaranMcNulty" rel="nofollow" target="_blank">Ciaran McNulty</a>, <a href="https://twitter.com/derickr" rel="nofollow" target="_blank">Derick Rethans</a> and <a href="https://twitter.com/philsturgeon" rel="nofollow" target="_blank">Phil Sturgeon</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://pbs.twimg.com/media/CjlUkGpUUAAvJ_U.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://pbs.twimg.com/media/CjlUkGpUUAAvJ_U.jpg" width="320" /></a></div>
<br />
Conference Day 2: Again a day filled with awesome talks by <a href="https://twitter.com/rdohms" rel="nofollow" target="_blank">Rafael Dohms</a>, <a href="https://twitter.com/Ocramius" rel="nofollow" target="_blank">Marco Pivetta</a>, <a href="https://twitter.com/dragonbe" rel="nofollow" target="_blank">Michelangelo van Dam</a> (me), a dual talk by <a href="https://twitter.com/s_bergmann" rel="nofollow" target="_blank">Sebastian Bergmann</a> and <a href="https://twitter.com/CiaranMcNulty" rel="nofollow" target="_blank">Ciaran McNulty</a> to be closed off by <a href="https://twitter.com/gojkoadzic" rel="nofollow" target="_blank">Gojko Adzic</a> who presented an amazing "The future of test automation" closing keynote.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJzEAuI1u0PteEpnFLDuUMZqvX9guyKPzPZDKpGpbiU4OlTDMmj012QnzRFXQCUDvDymZcZG4mNM3GNEkoQOlFnW3l422DXnmUG32n0FbrgYAD8qwuU140cu5r9-oTUbujB3cHQA/s1600/phpsrb16_day2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJzEAuI1u0PteEpnFLDuUMZqvX9guyKPzPZDKpGpbiU4OlTDMmj012QnzRFXQCUDvDymZcZG4mNM3GNEkoQOlFnW3l422DXnmUG32n0FbrgYAD8qwuU140cu5r9-oTUbujB3cHQA/s320/phpsrb16_day2.png" width="320" /></a></div>
<br />
Again, I would like to thank the organizers <a href="https://twitter.com/AcoGagic" rel="nofollow" target="_blank">Aco Gagic</a>, <a href="https://twitter.com/komita1981" rel="nofollow" target="_blank">Milan Popović</a> and <a href="https://twitter.com/nikolaposa" rel="nofollow" target="_blank">Nikola Poša</a> of <a href="https://twitter.com/hashtag/phpsrb16?src=hash" rel="nofollow" target="_blank">#PHPSrb16</a> for going way beyond expectations. You are awesome hosts and it was my privilege being part of this amazing event and taking home so many wonderful experiences.<br />
<br />
<div style="text-align: center;">
<b>I can recommend PHPSrbija Conference to every speaker!</b></div>
<br />
It was hard to say goodbye to the good friends I made at this conference, but every beginning has to have an end. So on Monday I started my way back home. But this time it was a bit more eventful as I had hoped for. Flights were delayed because of bad weather in Western Europe and once I arrived back in Belgium, I ended up without normal public transportation because of strikes. In the end, I litterly had to walk the last mile back home. But I made it safe and sound. This little setback was nothing compared to the great conference I had in Serbia. Can't wait for next year!<br />
<br />
<span style="background-color: transparent; background-image: url(data:image/png; border: none; cursor: pointer; display: none; height: 20px; left: 193px; opacity: 0.85; position: absolute; top: 2843px; width: 40px; z-index: 8675309;"></span><span style="background-color: transparent; background-image: url(data:image/png; border: none; cursor: pointer; display: none; height: 20px; left: 193px; opacity: 0.85; position: absolute; top: 2843px; width: 40px; z-index: 8675309;"></span>M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com0Belgrade, Serbia44.786568 20.44892159999994944.426118 19.803474599999948 45.147018 21.09436859999995tag:blogger.com,1999:blog-28215292.post-55999901325377832862016-02-06T17:13:00.000+01:002016-02-06T17:23:39.945+01:00PHP Arrays - The php array functions<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGvDlc9diMNAr6J-NUnq20qrz9S8BFSGosa2glwBFbVg5ep3EoxKN7l7W7P8c__s9aP7opNOYFPP4BijOldobN2Ruf65Um6Fzn8_-ViIDl4rHdJ4weOAvuiKCf4g-O4aAdy0e3Gg/s1600/15204888096_24f8966334_z.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGvDlc9diMNAr6J-NUnq20qrz9S8BFSGosa2glwBFbVg5ep3EoxKN7l7W7P8c__s9aP7opNOYFPP4BijOldobN2Ruf65Um6Fzn8_-ViIDl4rHdJ4weOAvuiKCf4g-O4aAdy0e3Gg/s1600/15204888096_24f8966334_z.jpg" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Source: <a href="https://www.flickr.com/photos/xavier33300/15204888096" rel="nofollow" target="_blank">Xavier33300 on Flickr.com</a></td></tr>
</tbody></table>
In my previous article about arrays (<a href="http://www.dragonbe.com/2016/01/php-arrays-basics.html" target="_blank">the basics</a>, <a href="http://www.dragonbe.com/2016/01/php-arrays-simple-operations.html" target="_blank">simple operations</a> and <a href="http://www.dragonbe.com/2016/01/php-arrays-associative-arrays-or-hash.html" target="_blank">associative arrays or hash maps</a>) I have shown what arrays are and what you can do with it. Now I want to dive into real fun and explain <a href="http://php.net/manual/en/ref.array.php" target="_blank">PHP's array functions</a> with real-world examples and how you can apply them in your day-to-day work.<br />
<br />
<h3>
Collection to select form key-values</h3>
Many of the website registration forms uses a country select element or an autocomplete input field using data from a database.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJupA32E8Z3nvQ6mOR5hHjGUoEVZwFebISxAehZAHco_Sx8LaTvyVIVCO-uMYiMHaoYxE_-Yn5cOe788OepRcZeUd7EPJtxmikFAQHbmiegd4QxGYfkuTUYYB2BISlhpu868evYQ/s1600/Screenshot+2016-02-04+16.39.11.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJupA32E8Z3nvQ6mOR5hHjGUoEVZwFebISxAehZAHco_Sx8LaTvyVIVCO-uMYiMHaoYxE_-Yn5cOe788OepRcZeUd7EPJtxmikFAQHbmiegd4QxGYfkuTUYYB2BISlhpu868evYQ/s1600/Screenshot+2016-02-04+16.39.11.png" /></a></div>
<br />
If this was a single PHP with HTML combined page, there was no problem as you could easily reuse the query made to collect the data. But when using an MVC approach where your controller needs to push the data it fetches from the backend to the form before the form can be passed to the view you're in for a treat. We're addressing the issues for an MVC approach here.<br />
<br />
Let's look at our country table first to get an impression how data is being stored in the database.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">+-----------+-------------+------+-----+---------+----------------+</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">| Field | Type | Null | Key | Default | Extra |</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">+-----------+-------------+------+-----+---------+----------------+</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">| id | int(11) | NO | PRI | NULL | auto_increment |</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">| iso | char(2) | NO | | NULL | |</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">| name | varchar(80) | NO | | NULL | |</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">| nicename | varchar(80) | NO | | NULL | |</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">| iso3 | char(3) | YES | | NULL | |</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">| numcode | smallint(6) | YES | | NULL | |</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">| phonecode | int(5) | NO | | NULL | |</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">+-----------+-------------+------+-----+---------+----------------+</span><br />
<br />
In order to use this data in our forms, the two fields "iso" and "printable_name" are most likely the fields that would make the most sense.<br />
<br />
Two approaches we can take here:<br />
<br />
<ol>
<li>we query our database for only those fields we need, with the requirement that we need to make a second database call when we need to populate our select field for country phone prefixes</li>
<li>we query all of our required fields "iso", "printable_name" and "phonecode" in one query and use PHP array functions to populate our select fields</li>
</ol>
<div>
We choose to take option 2.</div>
<div>
<br /></div>
<div>
Let's have a look on how most people do things nowadays. The first thing they do is retrieve the data from their backend in the controller. In the controller they prepare their form and pass the form back to the view.</div>
<div>
<br /></div>
<div>
<span style="color: #993333; font-family: monospace;">public function </span><span style="color: #6699cc; font-family: monospace;">registerAction</span><span style="color: #993333; font-family: monospace;">()<br />{<br /> </span><span style="color: #6699cc; font-family: monospace;">$form </span><span style="color: #993333; font-family: monospace;">= </span><span style="color: #6699cc; font-family: monospace;">$this</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">getForm</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #66cc66; font-family: monospace;">'member'</span><span style="color: #993333; font-family: monospace;">);<br /><br /> </span><span style="color: #6699cc; font-family: monospace;">$countryMapper </span><span style="color: #993333; font-family: monospace;">= new </span><span style="color: #6699cc; font-family: monospace;">CountryMapper</span><span style="color: #993333; font-family: monospace;">();<br /> </span><span style="color: #6699cc; font-family: monospace;">$countryList </span><span style="color: #993333; font-family: monospace;">= </span><span style="color: #6699cc; font-family: monospace;">$countryMapper</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">fetchAll</span><span style="color: #993333; font-family: monospace;">();<br /> </span><span style="color: #6699cc; font-family: monospace;">$countrySelect </span><span style="color: #993333; font-family: monospace;">= [];<br /> </span><span style="color: #6699cc; font-family: monospace;">$phoneSelect </span><span style="color: #993333; font-family: monospace;">= [];<br /> foreach (</span><span style="color: #6699cc; font-family: monospace;">$countryList </span><span style="color: #993333; font-family: monospace;">as </span><span style="color: #6699cc; font-family: monospace;">$country</span><span style="color: #993333; font-family: monospace;">) {<br /> </span><span style="color: #6699cc; font-family: monospace;">$countrySelect</span><span style="color: #993333; font-family: monospace;">[] = [<br /> </span><span style="color: #66cc66; font-family: monospace;">'iso' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #6699cc; font-family: monospace;">$country</span><span style="color: #993333; font-family: monospace;">[</span><span style="color: #66cc66; font-family: monospace;">'iso'</span><span style="color: #993333; font-family: monospace;">],<br /> </span><span style="color: #66cc66; font-family: monospace;">'nicename' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #6699cc; font-family: monospace;">$country</span><span style="color: #993333; font-family: monospace;">[</span><span style="color: #66cc66; font-family: monospace;">'nicename'</span><span style="color: #993333; font-family: monospace;">],<br /> ];<br /> </span><span style="color: #6699cc; font-family: monospace;">$phoneSelect</span><span style="color: #993333; font-family: monospace;">[] = [<br /> </span><span style="color: #66cc66; font-family: monospace;">'phonecode' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #6699cc; font-family: monospace;">$country</span><span style="color: #993333; font-family: monospace;">[</span><span style="color: #66cc66; font-family: monospace;">'phonecode'</span><span style="color: #993333; font-family: monospace;">],<br /> </span><span style="color: #66cc66; font-family: monospace;">'nicename' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #6699cc; font-family: monospace;">$country</span><span style="color: #993333; font-family: monospace;">[</span><span style="color: #66cc66; font-family: monospace;">'nicename'</span><span style="color: #993333; font-family: monospace;">],<br /> ];<br /> }<br /> </span><span style="color: #6699cc; font-family: monospace;">$form</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">getElement</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #66cc66; font-family: monospace;">'country'</span><span style="color: #993333; font-family: monospace;">)-></span><span style="color: #6699cc; font-family: monospace;">addMultiOptions</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #6699cc; font-family: monospace;">$countrySelect</span><span style="color: #993333; font-family: monospace;">);<br /> </span><span style="color: #6699cc; font-family: monospace;">$form</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">getElement</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #66cc66; font-family: monospace;">'phoneprefix'</span><span style="color: #993333; font-family: monospace;">)-></span><span style="color: #6699cc; font-family: monospace;">addMultiOptions</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #6699cc; font-family: monospace;">$phoneSelect</span><span style="color: #993333; font-family: monospace;">);<br /><br /> if (isset (</span><span style="color: #6699cc; font-family: monospace;">$this</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">session</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">memberForm</span><span style="color: #993333; font-family: monospace;">)) {<br /> </span><span style="color: #6699cc; font-family: monospace;">$form </span><span style="color: #993333; font-family: monospace;">= </span><span style="color: #6699cc; font-family: monospace;">unserialize</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #6699cc; font-family: monospace;">$this</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">session</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">memberForm</span><span style="color: #993333; font-family: monospace;">);<br /> unset (</span><span style="color: #6699cc; font-family: monospace;">$this</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">session</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">memberForm</span><span style="color: #993333; font-family: monospace;">);<br /> }<br /> return [<br /> </span><span style="color: #66cc66; font-family: monospace;">'memberForm' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #6699cc; font-family: monospace;">$form</span><span style="color: #993333; font-family: monospace;">,<br /> ];<br />}</span></div>
<div>
<br /></div>
<div>
So, within the controller a loop is created to populate two field elements "country" and "phoneprefix". Even though this is an easy approach and works in most cases, the moment you have a lot of data to process, this kind of approach is slowing down your application. Say hello to two power functions: "<a href="http://php.net/manual/en/function.array-walk.php" rel="nofollow" target="_blank">array_walk</a>" and "<a href="http://php.net/manual/en/function.array-intersect-key.php" rel="nofollow" target="_blank">array_intersect_key</a>"!</div>
<div>
<br /></div>
<div>
PHP function "<a href="http://php.net/manual/en/function.array-walk.php" rel="nofollow" target="_blank">array_walk</a>" allows you to apply user functionality to each element of that array. This means we can apply our second functionality "<a href="http://php.net/manual/en/function.array-intersect-key.php" rel="nofollow" target="_blank">array_intersect_key</a>" on each row.</div>
<div>
<br /></div>
<div>
PHP function "<a href="http://php.net/manual/en/function.array-intersect-key.php" rel="nofollow" target="_blank">array_intersect_key</a>" gives us the ability to take the common elements from our country list row and the keys we provide as second argument.</div>
<div>
<br /></div>
<div>
<span style="color: #6699cc; font-family: monospace;">$countrySelect </span><span style="color: #993333; font-family: monospace;">= [];</span></div>
<div>
<span style="color: #6699cc; font-family: monospace;">array_walk</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #6699cc; font-family: monospace;">$countryList</span><span style="color: #993333; font-family: monospace;">, function (</span><span style="color: #6699cc; font-family: monospace;">$row</span><span style="color: #993333; font-family: monospace;">, </span><span style="color: #6699cc; font-family: monospace;">$key</span><span style="color: #993333; font-family: monospace;">) use (&</span><span style="color: #6699cc; font-family: monospace;">$countrySelect</span><span style="color: #993333; font-family: monospace;">) {<br /> </span><span style="color: #6699cc; font-family: monospace;">$countrySelect</span><span style="color: #993333; font-family: monospace;">[] = </span><span style="color: #6699cc; font-family: monospace;">array_intersect_key</span><span style="color: #993333; font-family: monospace;">(<br /> </span><span style="color: #6699cc; font-family: monospace;">$row</span><span style="color: #993333; font-family: monospace;">,<br /> [</span><span style="color: #66cc66; font-family: monospace;">'iso' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #6699cc; font-family: monospace;">null</span><span style="color: #993333; font-family: monospace;">, </span><span style="color: #66cc66; font-family: monospace;">'nicename' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #6699cc; font-family: monospace;">null</span><span style="color: #993333; font-family: monospace;">]<br /> );<br />});</span></div>
<div>
<span style="color: #993333; font-family: monospace;"><br /></span><span style="color: #6699cc; font-family: monospace;">$phoneSelect </span><span style="color: #993333; font-family: monospace;">= [];</span></div>
<div>
<span style="color: #6699cc; font-family: monospace;">array_walk</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #6699cc; font-family: monospace;">$countryList</span><span style="color: #993333; font-family: monospace;">, function (</span><span style="color: #6699cc; font-family: monospace;">$row</span><span style="color: #993333; font-family: monospace;">, </span><span style="color: #6699cc; font-family: monospace;">$key</span><span style="color: #993333; font-family: monospace;">) use (&</span><span style="color: #6699cc; font-family: monospace;">$phoneSelect</span><span style="color: #993333; font-family: monospace;">) {<br /> </span><span style="color: #6699cc; font-family: monospace;">$phoneSelect</span><span style="color: #993333; font-family: monospace;">[] = </span><span style="color: #6699cc; font-family: monospace;">array_intersect_key</span><span style="color: #993333; font-family: monospace;">(<br /> </span><span style="color: #6699cc; font-family: monospace;">$row</span><span style="color: #993333; font-family: monospace;">,<br /> [</span><span style="color: #66cc66; font-family: monospace;">'iso' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #6699cc; font-family: monospace;">null</span><span style="color: #993333; font-family: monospace;">, </span><span style="color: #66cc66; font-family: monospace;">'phonecode' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #6699cc; font-family: monospace;">null</span><span style="color: #993333; font-family: monospace;">]<br /> );<br />});</span></div>
<div>
<br /></div>
<div>
Now we have two arrays that contain only the elements we can just pass on to the form select elements. And the whole controller action now looks like this:</div>
<div>
<br /></div>
<div>
<span style="color: #993333; font-family: monospace;">public function </span><span style="color: #6699cc; font-family: monospace;">registerAction</span><span style="color: #993333; font-family: monospace;">()<br />{<br /> </span><span style="color: #6699cc; font-family: monospace;">$form </span><span style="color: #993333; font-family: monospace;">= </span><span style="color: #6699cc; font-family: monospace;">$this</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">getForm</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #66cc66; font-family: monospace;">'member'</span><span style="color: #993333; font-family: monospace;">);<br /><br /> </span><span style="color: #6699cc; font-family: monospace;">$countryMapper </span><span style="color: #993333; font-family: monospace;">= new </span><span style="color: #6699cc; font-family: monospace;">CountryMapper</span><span style="color: #993333; font-family: monospace;">();<br /> </span><span style="color: #6699cc; font-family: monospace;">$countryList </span><span style="color: #993333; font-family: monospace;">= </span><span style="color: #6699cc; font-family: monospace;">$countryMapper</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">fetchAll</span><span style="color: #993333; font-family: monospace;">();<br /> </span><span style="color: #6699cc; font-family: monospace;">$countrySelect </span><span style="color: #993333; font-family: monospace;">= [];<br /> </span><span style="color: #6699cc; font-family: monospace;">array_walk</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #6699cc; font-family: monospace;">$countryList</span><span style="color: #993333; font-family: monospace;">, function (</span><span style="color: #6699cc; font-family: monospace;">$row</span><span style="color: #993333; font-family: monospace;">, </span><span style="color: #6699cc; font-family: monospace;">$key</span><span style="color: #993333; font-family: monospace;">) use (&</span><span style="color: #6699cc; font-family: monospace;">$countrySelect</span><span style="color: #993333; font-family: monospace;">) {<br /> </span><span style="color: #6699cc; font-family: monospace;">$countrySelect</span><span style="color: #993333; font-family: monospace;">[] = </span><span style="color: #6699cc; font-family: monospace;">array_intersect_key</span><span style="color: #993333; font-family: monospace;">(<br /> </span><span style="color: #6699cc; font-family: monospace;">$row</span><span style="color: #993333; font-family: monospace;">,<br /> [</span><span style="color: #66cc66; font-family: monospace;">'iso' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #6699cc; font-family: monospace;">null</span><span style="color: #993333; font-family: monospace;">, </span><span style="color: #66cc66; font-family: monospace;">'nicename' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #6699cc; font-family: monospace;">null</span><span style="color: #993333; font-family: monospace;">]<br /> );<br /> }); </span></div>
<div>
<span style="color: #993333; font-family: monospace;"><br /> </span><span style="color: #6699cc; font-family: monospace;">$phoneSelect </span><span style="color: #993333; font-family: monospace;">= [];<br /> </span><span style="color: #6699cc; font-family: monospace;">array_walk</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #6699cc; font-family: monospace;">$countryList</span><span style="color: #993333; font-family: monospace;">, function (</span><span style="color: #6699cc; font-family: monospace;">$row</span><span style="color: #993333; font-family: monospace;">, </span><span style="color: #6699cc; font-family: monospace;">$key</span><span style="color: #993333; font-family: monospace;">) use (&</span><span style="color: #6699cc; font-family: monospace;">$phoneSelect</span><span style="color: #993333; font-family: monospace;">) {<br /> </span><span style="color: #6699cc; font-family: monospace;">$phoneSelect</span><span style="color: #993333; font-family: monospace;">[] = </span><span style="color: #6699cc; font-family: monospace;">array_intersect_key</span><span style="color: #993333; font-family: monospace;">(<br /> </span><span style="color: #6699cc; font-family: monospace;">$row</span><span style="color: #993333; font-family: monospace;">,<br /> [</span><span style="color: #66cc66; font-family: monospace;">'iso' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #6699cc; font-family: monospace;">null</span><span style="color: #993333; font-family: monospace;">, </span><span style="color: #66cc66; font-family: monospace;">'phonecode' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #6699cc; font-family: monospace;">null</span><span style="color: #993333; font-family: monospace;">]<br /> );<br /> });<br /> </span><span style="color: #6699cc; font-family: monospace;">$form</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">getElement</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #66cc66; font-family: monospace;">'country'</span><span style="color: #993333; font-family: monospace;">)-></span><span style="color: #6699cc; font-family: monospace;">addMultiOptions</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #6699cc; font-family: monospace;">$countrySelect</span><span style="color: #993333; font-family: monospace;">);<br /> </span><span style="color: #6699cc; font-family: monospace;">$form</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">getElement</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #66cc66; font-family: monospace;">'phoneprefix'</span><span style="color: #993333; font-family: monospace;">)-></span><span style="color: #6699cc; font-family: monospace;">addMultiOptions</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #6699cc; font-family: monospace;">$phoneSelect</span><span style="color: #993333; font-family: monospace;">);<br /><br /> if (isset (</span><span style="color: #6699cc; font-family: monospace;">$this</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">session</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">memberForm</span><span style="color: #993333; font-family: monospace;">)) {<br /> </span><span style="color: #6699cc; font-family: monospace;">$form </span><span style="color: #993333; font-family: monospace;">= </span><span style="color: #6699cc; font-family: monospace;">unserialize</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #6699cc; font-family: monospace;">$this</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">session</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">memberForm</span><span style="color: #993333; font-family: monospace;">);<br /> unset (</span><span style="color: #6699cc; font-family: monospace;">$this</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">session</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">memberForm</span><span style="color: #993333; font-family: monospace;">);<br /> }<br /> return [<br /> </span><span style="color: #66cc66; font-family: monospace;">'memberForm' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #6699cc; font-family: monospace;">$form</span><span style="color: #993333; font-family: monospace;">,<br /> ];<br />}</span></div>
<div>
<span style="color: #993333; font-family: monospace;"><br /></span></div>
<h3>
Finding primary keys from a collection</h3>
<div>
Another common pattern I see is when developers need to pull ID's from a collection of elements to pass on to a next request. Again, foreach is the common used loop to iterate over each element, adding the ID property to another array which then gets passed on to the query.</div>
<div>
<br /></div>
<div>
Let's first look our code that we're going to process.</div>
<div>
<br /></div>
<div>
<span style="color: #993333; font-family: monospace;">class </span><span style="color: #6699cc; font-family: monospace;">PhpFunction </span><span style="color: #993333; font-family: monospace;">{<br /> public </span><span style="color: #6699cc; font-family: monospace;">$id</span><span style="color: #993333; font-family: monospace;">;<br /> public </span><span style="color: #6699cc; font-family: monospace;">$label</span><span style="color: #993333; font-family: monospace;">;<br /><br /> public function </span><span style="color: #6699cc; font-family: monospace;">__construct</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #6699cc; font-family: monospace;">$id</span><span style="color: #993333; font-family: monospace;">, </span><span style="color: #6699cc; font-family: monospace;">$label</span><span style="color: #993333; font-family: monospace;">)<br /> {<br /> </span><span style="color: #6699cc; font-family: monospace;">$this</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">id </span><span style="color: #993333; font-family: monospace;">= </span><span style="color: #6699cc; font-family: monospace;">$id</span><span style="color: #993333; font-family: monospace;">;<br /> </span><span style="color: #6699cc; font-family: monospace;">$this</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">label </span><span style="color: #993333; font-family: monospace;">= </span><span style="color: #6699cc; font-family: monospace;">$label</span><span style="color: #993333; font-family: monospace;">;<br /> }<br />} </span><span style="color: #6699cc; font-family: monospace;">$functions </span><span style="color: #993333; font-family: monospace;">= [<br /> new </span><span style="color: #6699cc; font-family: monospace;">PhpFunction</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #6699cc; font-family: monospace;">123</span><span style="color: #993333; font-family: monospace;">, </span><span style="color: #66cc66; font-family: monospace;">'array_map'</span><span style="color: #993333; font-family: monospace;">),<br /> new </span><span style="color: #6699cc; font-family: monospace;">PhpFunction</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #6699cc; font-family: monospace;">124</span><span style="color: #993333; font-family: monospace;">, </span><span style="color: #66cc66; font-family: monospace;">'array_merge_recursive'</span><span style="color: #993333; font-family: monospace;">),<br /> new </span><span style="color: #6699cc; font-family: monospace;">PhpFunction</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #6699cc; font-family: monospace;">125</span><span style="color: #993333; font-family: monospace;">, </span><span style="color: #66cc66; font-family: monospace;">'array_merge'</span><span style="color: #993333; font-family: monospace;">),<br />];</span></div>
<div>
<br /></div>
<div>
Now this example is only containing 3 elements, but when you look at the <a href="http://php.net/">php.net</a> website there are thousands of functions, so consider this is a huge collection of php functions.</div>
<div>
<br /></div>
<div>
In many cases I see something like the following code to retrieve the ID's from this collection:</div>
<div>
<br /></div>
<div>
<span style="color: #6699cc; font-family: monospace;">$functionIds </span><span style="color: #993333; font-family: monospace;">= [];<br />foreach (</span><span style="color: #6699cc; font-family: monospace;">$functions </span><span style="color: #993333; font-family: monospace;">as </span><span style="color: #6699cc; font-family: monospace;">$function</span><span style="color: #993333; font-family: monospace;">) {<br /> </span><span style="color: #6699cc; font-family: monospace;">$functionIds</span><span style="color: #993333; font-family: monospace;">[] = </span><span style="color: #6699cc; font-family: monospace;">$function</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">id</span><span style="color: #993333; font-family: monospace;">;<br />}</span></div>
<div>
<br /></div>
<div>
Even though this is a common pattern, I would prefer to use a native PHP function for processing this. Say hello to "array_map", the function that allows you to use a custom functionality on each element of the given array.</div>
<div>
<br /></div>
<div>
<span style="color: #6699cc; font-family: monospace;">$functionIds </span><span style="color: #993333; font-family: monospace;">= </span><span style="color: #6699cc; font-family: monospace;">array_map</span><span style="color: #993333; font-family: monospace;">(function (</span><span style="color: #6699cc; font-family: monospace;">$element</span><span style="color: #993333; font-family: monospace;">) {<br /> return </span><span style="color: #6699cc; font-family: monospace;">$element</span><span style="color: #993333; font-family: monospace;">-></span><span style="color: #6699cc; font-family: monospace;">id</span><span style="color: #993333; font-family: monospace;">;<br />}, </span><span style="color: #6699cc; font-family: monospace;">$functions</span><span style="color: #993333; font-family: monospace;">);</span></div>
<div>
<br /></div>
<div>
The result is exactly the same, but now using PHP's native C power processing huge arrays goes a bit faster than the "foreach"-loop.</div>
<div>
<br /></div>
<div>
Next article we're looking at more common patterns for processing arrays. Love to see you again.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com0tag:blogger.com,1999:blog-28215292.post-81843961384815766842016-01-14T10:30:00.000+01:002016-01-14T10:30:03.388+01:00PHP Arrays - Associative Arrays or Hash Maps<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWg4MM54be7oNLoddXzV1aQm3EL9oElWYWzROghntRsirB-EME5OJtpJnjygh8ahU629xPJ7o92A1j76AgZhfO-CnpevTGWlVbcmgwtnFCB_ncU3ptlNhEFCBK8RjhWSZQZCPy4g/s1600/associative_arrays_550.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWg4MM54be7oNLoddXzV1aQm3EL9oElWYWzROghntRsirB-EME5OJtpJnjygh8ahU629xPJ7o92A1j76AgZhfO-CnpevTGWlVbcmgwtnFCB_ncU3ptlNhEFCBK8RjhWSZQZCPy4g/s1600/associative_arrays_550.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Associative array or hash maps are listings of key and value pairs with a posibility to nest additional keys and values. An associative array is a very powerful construct within <a href="http://www.php.net/" rel="nofollow" target="_blank">PHP</a>.<br />
<br />
In our <a href="http://www.dragonbe.com/2016/01/php-arrays-simple-operations.html">previous article</a> we discussed simple arrays, which in their turn are indexed associative arrays under the hood. Take the following example:<br />
<br />
<span style="color: #6699cc; font-family: monospace;">$array </span><span style="color: #993333; font-family: monospace;">= [<br /> </span><span style="color: #66cc66; font-family: monospace;">'apple'</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'banana'</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'chocolate'</span><span style="color: #993333; font-family: monospace;">,<br />]; </span><br />
<br />
Is in fact an indexed associative array under the hood:<br />
<br />
<span style="color: #6699cc; font-family: monospace;">$array </span><span style="color: #993333; font-family: monospace;">= [<br /> </span><span style="color: #6699cc; font-family: monospace;">0 </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #66cc66; font-family: monospace;">'apple'</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #6699cc; font-family: monospace;">1 </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #66cc66; font-family: monospace;">'banana'</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #6699cc; font-family: monospace;">2 </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #66cc66; font-family: monospace;">'chocolate'</span><span style="color: #993333; font-family: monospace;">,<br />]; </span><br />
<br />
But associative arrays can be so much more than just an indexed array, and you will find many database operations returning arrays where the fields of a table are the keys in the array while their values are also the values within the array.<br />
<br />
<span style="color: #6699cc; font-family: monospace;">$productRowData </span><span style="color: #993333; font-family: monospace;">= [<br /> </span><span style="color: #66cc66; font-family: monospace;">'product_id' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #6699cc; font-family: monospace;">1234</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'brand_id' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #6699cc; font-family: monospace;">321</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'product_name' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #66cc66; font-family: monospace;">'Our awesome product'</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'prodcut_description' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #66cc66; font-family: monospace;">'This is our most awesome product.'</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'product_sku' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #66cc66; font-family: monospace;">'ABC1234-XYZ'</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'product_price' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #6699cc; font-family: monospace;">59.95</span><span style="color: #993333; font-family: monospace;">,<br />];</span><br />
<br />
Another example of use is to store configuration information in a PHP array, like Zend Framework does. It's maybe why they call it the "Array Framework". But it's actually a good approach to store configuration settings inside a PHP array as you don't need to parse another format like INI, XML, YAML, JSON or CSV, saving a couple of CPU cycles loading the configuration for your application. Once parsed, it will be represented as an array anyways, maybe serialized for persistance.<br />
<br />
<span style="color: #6699cc; font-family: monospace;">$dbConfig </span><span style="color: #993333; font-family: monospace;">= [<br /> </span><span style="color: #66cc66; font-family: monospace;">'db' </span><span style="color: #993333; font-family: monospace;">=> [<br /> </span><span style="color: #66cc66; font-family: monospace;">'erp' </span><span style="color: #993333; font-family: monospace;">=> [<br /> </span><span style="color: #66cc66; font-family: monospace;">'host' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #66cc66; font-family: monospace;">'123.123.456.456'</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'port' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #6699cc; font-family: monospace;">3306</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'username' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #66cc66; font-family: monospace;">'erp_user'</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'password' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #66cc66; font-family: monospace;">'v3rRy$ecR3tP@ssMor7! '</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'dbname' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #66cc66; font-family: monospace;">'erp'</span><span style="color: #993333; font-family: monospace;">,<br /> ],<br /> </span><span style="color: #66cc66; font-family: monospace;">'crm' </span><span style="color: #993333; font-family: monospace;">=> [<br /> </span><span style="color: #66cc66; font-family: monospace;">'host' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #66cc66; font-family: monospace;">'123.123.426.426'</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'port' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #6699cc; font-family: monospace;">3306</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'username' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #66cc66; font-family: monospace;">'crm_user'</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'password' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #66cc66; font-family: monospace;">' Y0u L1k3 f1&h 4nD Ch1p$?! '</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'dbname' </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #66cc66; font-family: monospace;">'crm'</span><span style="color: #993333; font-family: monospace;">,<br /> ],<br /> ],<br />];</span><br />
<br />
How can we iterate over these values? The easiest way is to use "foreach()" as we can define the key and value in the iteration construction:<br />
<br />
<span style="color: #993333; font-family: monospace;">foreach (</span><span style="color: #6699cc; font-family: monospace;">$productRowData </span><span style="color: #993333; font-family: monospace;">as </span><span style="color: #6699cc; font-family: monospace;">$key </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #6699cc; font-family: monospace;">$value</span><span style="color: #993333; font-family: monospace;">) {<br /> echo </span><span style="color: #66cc66; font-family: monospace;">'key : ' </span><span style="color: #993333; font-family: monospace;">. </span><span style="color: #6699cc; font-family: monospace;">$key </span><span style="color: #993333; font-family: monospace;">. </span><span style="color: #6699cc; font-family: monospace;">PHP_EOL</span><span style="color: #993333; font-family: monospace;">;<br /> echo </span><span style="color: #66cc66; font-family: monospace;">'value: ' </span><span style="color: #993333; font-family: monospace;">. </span><span style="color: #6699cc; font-family: monospace;">$value </span><span style="color: #993333; font-family: monospace;">. </span><span style="color: #6699cc; font-family: monospace;">PHP_EOL</span><span style="color: #993333; font-family: monospace;">;<br /> echo </span><span style="color: #6699cc; font-family: monospace;">PHP_EOL</span><span style="color: #993333; font-family: monospace;">;<br />}</span><br />
<br />
For the other loops like "for", "do-while" and "while-do" we need to do a bit of extra work. As we don't have direct access to the "index" of the associative array, we cannot iterate over the keys. So we fetch the keys as a seperate array with "array_keys" function.<br />
<br />
<span style="color: #6699cc; font-family: monospace;">$count </span><span style="color: #993333; font-family: monospace;">= </span><span style="color: #6699cc; font-family: monospace;">count</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #6699cc; font-family: monospace;">$productRowData</span><span style="color: #993333; font-family: monospace;">); </span><br />
<span style="color: #6699cc; font-family: monospace;">$keys </span><span style="color: #993333; font-family: monospace;">= </span><span style="color: #6699cc; font-family: monospace;">array_keys</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #6699cc; font-family: monospace;">$productRowData</span><span style="color: #993333; font-family: monospace;">);<br /><br />echo </span><span style="color: #66cc66; font-family: monospace;">'== Iteration with for' </span><span style="color: #993333; font-family: monospace;">. </span><span style="color: #6699cc; font-family: monospace;">PHP_EOL</span><span style="color: #993333; font-family: monospace;">;<br />for (</span><span style="color: #6699cc; font-family: monospace;">$i </span><span style="color: #993333; font-family: monospace;">= </span><span style="color: #6699cc; font-family: monospace;">0</span><span style="color: #993333; font-family: monospace;">; </span><span style="color: #6699cc; font-family: monospace;">$i </span><span style="color: #993333; font-family: monospace;">< </span><span style="color: #6699cc; font-family: monospace;">$count</span><span style="color: #993333; font-family: monospace;">; </span><span style="color: #6699cc; font-family: monospace;">$i</span><span style="color: #993333; font-family: monospace;">++) {<br /> echo </span><span style="color: #66cc66; font-family: monospace;">'key : ' </span><span style="color: #993333; font-family: monospace;">. </span><span style="color: #6699cc; font-family: monospace;">$keys</span><span style="color: #993333; font-family: monospace;">[</span><span style="color: #6699cc; font-family: monospace;">$i</span><span style="color: #993333; font-family: monospace;">] . </span><span style="color: #6699cc; font-family: monospace;">PHP_EOL</span><span style="color: #993333; font-family: monospace;">;<br /> echo </span><span style="color: #66cc66; font-family: monospace;">'value: ' </span><span style="color: #993333; font-family: monospace;">. </span><span style="color: #6699cc; font-family: monospace;">$productRowData</span><span style="color: #993333; font-family: monospace;">[</span><span style="color: #6699cc; font-family: monospace;">$keys</span><span style="color: #993333; font-family: monospace;">[</span><span style="color: #6699cc; font-family: monospace;">$i</span><span style="color: #993333; font-family: monospace;">]] . </span><span style="color: #6699cc; font-family: monospace;">PHP_EOL</span><span style="color: #993333; font-family: monospace;">;<br /> echo </span><span style="color: #6699cc; font-family: monospace;">PHP_EOL</span><span style="color: #993333; font-family: monospace;">;<br />}<br /><br />echo </span><span style="color: #66cc66; font-family: monospace;">'== Iteration with do-while' </span><span style="color: #993333; font-family: monospace;">. </span><span style="color: #6699cc; font-family: monospace;">PHP_EOL</span><span style="color: #993333; font-family: monospace;">; </span><br />
<span style="color: #6699cc; font-family: monospace;">$i </span><span style="color: #993333; font-family: monospace;">= </span><span style="color: #6699cc; font-family: monospace;">0</span><span style="color: #993333; font-family: monospace;">;<br />do {<br /> echo </span><span style="color: #66cc66; font-family: monospace;">'key : ' </span><span style="color: #993333; font-family: monospace;">. </span><span style="color: #6699cc; font-family: monospace;">$keys</span><span style="color: #993333; font-family: monospace;">[</span><span style="color: #6699cc; font-family: monospace;">$i</span><span style="color: #993333; font-family: monospace;">] . </span><span style="color: #6699cc; font-family: monospace;">PHP_EOL</span><span style="color: #993333; font-family: monospace;">;<br /> echo </span><span style="color: #66cc66; font-family: monospace;">'value: ' </span><span style="color: #993333; font-family: monospace;">. </span><span style="color: #6699cc; font-family: monospace;">$productRowData</span><span style="color: #993333; font-family: monospace;">[</span><span style="color: #6699cc; font-family: monospace;">$keys</span><span style="color: #993333; font-family: monospace;">[</span><span style="color: #6699cc; font-family: monospace;">$i</span><span style="color: #993333; font-family: monospace;">]] . </span><span style="color: #6699cc; font-family: monospace;">PHP_EOL</span><span style="color: #993333; font-family: monospace;">;<br /> echo </span><span style="color: #6699cc; font-family: monospace;">PHP_EOL</span><span style="color: #993333; font-family: monospace;">;<br /> </span><span style="color: #6699cc; font-family: monospace;">$i</span><span style="color: #993333; font-family: monospace;">++;<br />} while (</span><span style="color: #6699cc; font-family: monospace;">$i </span><span style="color: #993333; font-family: monospace;">< </span><span style="color: #6699cc; font-family: monospace;">$count</span><span style="color: #993333; font-family: monospace;">);<br /><br />echo </span><span style="color: #66cc66; font-family: monospace;">'== Iteration with while-do' </span><span style="color: #993333; font-family: monospace;">. </span><span style="color: #6699cc; font-family: monospace;">PHP_EOL</span><span style="color: #993333; font-family: monospace;">; </span><br />
<span style="color: #6699cc; font-family: monospace;">$i </span><span style="color: #993333; font-family: monospace;">= </span><span style="color: #6699cc; font-family: monospace;">0</span><span style="color: #993333; font-family: monospace;">;<br />while (</span><span style="color: #6699cc; font-family: monospace;">$i </span><span style="color: #993333; font-family: monospace;">< </span><span style="color: #6699cc; font-family: monospace;">$count</span><span style="color: #993333; font-family: monospace;">) {<br /> echo </span><span style="color: #66cc66; font-family: monospace;">'key : ' </span><span style="color: #993333; font-family: monospace;">. </span><span style="color: #6699cc; font-family: monospace;">$keys</span><span style="color: #993333; font-family: monospace;">[</span><span style="color: #6699cc; font-family: monospace;">$i</span><span style="color: #993333; font-family: monospace;">] . </span><span style="color: #6699cc; font-family: monospace;">PHP_EOL</span><span style="color: #993333; font-family: monospace;">;<br /> echo </span><span style="color: #66cc66; font-family: monospace;">'value: ' </span><span style="color: #993333; font-family: monospace;">. </span><span style="color: #6699cc; font-family: monospace;">$productRowData</span><span style="color: #993333; font-family: monospace;">[</span><span style="color: #6699cc; font-family: monospace;">$keys</span><span style="color: #993333; font-family: monospace;">[</span><span style="color: #6699cc; font-family: monospace;">$i</span><span style="color: #993333; font-family: monospace;">]] . </span><span style="color: #6699cc; font-family: monospace;">PHP_EOL</span><span style="color: #993333; font-family: monospace;">;<br /> echo </span><span style="color: #6699cc; font-family: monospace;">PHP_EOL</span><span style="color: #993333; font-family: monospace;">;<br /> </span><span style="color: #6699cc; font-family: monospace;">$i</span><span style="color: #993333; font-family: monospace;">++;<br />}</span><br />
<br />
Both loops "for" and "while-do" will <b>first evaluate</b> the given condition before they start their iteration. The "do-while" loop will execute the loop <b>at least once</b> before validating a condition. In some conditions this can be convenient.<br />
<br />
What if we want to look for a specific value, should we iterate over each element until we find the value? Let's say we are looking in our configuration for the array containing the value "123.123.426.426" because we found it in one of our logs. A very common practice is the following example:<br />
<br />
<span style="color: #6699cc; font-family: monospace;">$searchResult </span><span style="color: #993333; font-family: monospace;">= </span><span style="color: #6699cc; font-family: monospace;">null</span><span style="color: #993333; font-family: monospace;">; </span><br />
<span style="color: #6699cc; font-family: monospace;">$search </span><span style="color: #993333; font-family: monospace;">= </span><span style="color: #66cc66; font-family: monospace;">'123.123.426.426'</span><span style="color: #993333; font-family: monospace;">; </span><br />
<span style="color: #993333; font-family: monospace;"><br />foreach (</span><span style="color: #6699cc; font-family: monospace;">$dbConfig </span><span style="color: #993333; font-family: monospace;">as </span><span style="color: #6699cc; font-family: monospace;">$db</span><span style="color: #993333; font-family: monospace;">) {<br /> foreach (</span><span style="color: #6699cc; font-family: monospace;">$db </span><span style="color: #993333; font-family: monospace;">as </span><span style="color: #6699cc; font-family: monospace;">$target </span><span style="color: #993333; font-family: monospace;">=> </span><span style="color: #6699cc; font-family: monospace;">$dbSettings</span><span style="color: #993333; font-family: monospace;">) {<br /> if (</span><span style="color: #6699cc; font-family: monospace;">$search </span><span style="color: #993333; font-family: monospace;">=== </span><span style="color: #6699cc; font-family: monospace;">$dbSettings</span><span style="color: #993333; font-family: monospace;">[</span><span style="color: #66cc66; font-family: monospace;">'host'</span><span style="color: #993333; font-family: monospace;">]) {<br /> </span><span style="color: #6699cc; font-family: monospace;">$searchResult </span><span style="color: #993333; font-family: monospace;">= </span><span style="color: #6699cc; font-family: monospace;">$dbSettings</span><span style="color: #993333; font-family: monospace;">;<br /> }<br /> }<br />} </span><br />
<span style="color: #cc8800; font-family: monospace;">// do something with $searchResult</span><br />
<br />
This is a very common practice I come accross and even though it's not a bad practice, there are php array functions available that do the trick as well. In this case, I choose "array_filter" to quickly retrieve the correct array.<br />
<br />
<span style="color: #993333; font-family: monospace;">foreach (</span><span style="color: #6699cc; font-family: monospace;">$dbConfig </span><span style="color: #993333; font-family: monospace;">as </span><span style="color: #6699cc; font-family: monospace;">$db</span><span style="color: #993333; font-family: monospace;">) {<br /> </span><span style="color: #6699cc; font-family: monospace;">$searchResult </span><span style="color: #993333; font-family: monospace;">= </span><span style="color: #6699cc; font-family: monospace;">array_filter</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #6699cc; font-family: monospace;">$db</span><span style="color: #993333; font-family: monospace;">, function (</span><span style="color: #6699cc; font-family: monospace;">$v</span><span style="color: #993333; font-family: monospace;">) use (</span><span style="color: #6699cc; font-family: monospace;">$search</span><span style="color: #993333; font-family: monospace;">) {<br /> return </span><span style="color: #6699cc; font-family: monospace;">in_array</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #6699cc; font-family: monospace;">$search</span><span style="color: #993333; font-family: monospace;">, </span><span style="color: #6699cc; font-family: monospace;">$v</span><span style="color: #993333; font-family: monospace;">);<br /> });<br />} </span><br />
<span style="color: #cc8800; font-family: monospace;">// do something with $searchResult</span><br />
<br />
Above functionality allows us to keep a clear understanding what's going on and we reduce the amount of iterations we need to execute. Consider doing this on an array with a couple of 1000 entries.<br />
<br />
In our next article we're going to look a bit more at the various PHP array functions you can use in your day-to-day application development.M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com0tag:blogger.com,1999:blog-28215292.post-24691935858589085532016-01-06T13:30:00.000+01:002016-01-06T13:30:01.491+01:00PHP arrays - simple operations<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYxRI_fIwBQIPcFOLp2gJi0l4_wPHgI8wlGXWoebqDqMFWWT3442wJOkoP0wyxeaZXdtuGasdVbdzh9geJHGeAmXiM3Db8E-jnK4iHXk8tIS7jXJ4EL6NLC5Xhi3tGUbpGW2H4hg/s1600/9399118987_7e6bd17fd1_z.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="232" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYxRI_fIwBQIPcFOLp2gJi0l4_wPHgI8wlGXWoebqDqMFWWT3442wJOkoP0wyxeaZXdtuGasdVbdzh9geJHGeAmXiM3Db8E-jnK4iHXk8tIS7jXJ4EL6NLC5Xhi3tGUbpGW2H4hg/s400/9399118987_7e6bd17fd1_z.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Source: <a href="https://www.flickr.com/photos/meanderingwa/9399118987" rel="nofollow" target="_blank">Flickr.com - Upupa4me</a></td></tr>
</tbody></table>
Like all things in life, we need to start with simple things. So, in order to understand what arrays are in PHP, we need to take a look at the <a href="http://php.net/manual/en/language.types.array.php" rel="nofollow" target="_blank">PHP manual</a> to read what it is all about:<br />
<blockquote class="tr_bq">
<i>An array in PHP is actually an ordered map. A map is a type that associates values to keys. This type is optimized for several different uses; it can be treated as an array, list (vector), hash table (an implementation of a map), dictionary, collection, stack, queue, and probably more.</i></blockquote>
The thing with PHP is that an array is probably one of the most used data structures in web applications build with PHP and used for a wide variety of purposes.<br />
<br />
Let's look at a first usage of an array: storing multiple values in a list.<br />
<br />
<span style="color: #6699cc; font-family: monospace;"><?php<br />$array </span><span style="color: #993333; font-family: monospace;">= [<br /> </span><span style="color: #66cc66; font-family: monospace;">'foo'</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'bar'</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'baz'</span><span style="color: #993333; font-family: monospace;">,<br />];</span><br />
<br />
This is a PHP array with 3 elements. Now we can add an element at the end of this array.<br />
<br />
<span style="color: #cc8800; font-family: monospace;">// Adding an element at the of the array </span><br />
<span style="color: #6699cc; font-family: monospace;">array_push</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #6699cc; font-family: monospace;">$array</span><span style="color: #993333; font-family: monospace;">, </span><span style="color: #66cc66; font-family: monospace;">'foobar'</span><span style="color: #993333; font-family: monospace;">);</span><br />
<br />
Or even more efficient:<br />
<br />
<span style="color: #6699cc; font-family: monospace;">$array</span><span style="color: #993333; font-family: monospace;">[] = </span><span style="color: #66cc66; font-family: monospace;">'barbaz'</span><span style="color: #993333; font-family: monospace;">;</span><br />
<br />
Now our array looks like this:<br />
<br />
<span style="color: #6699cc; font-family: monospace;">$array </span><span style="color: #993333; font-family: monospace;">= [<br /> </span><span style="color: #66cc66; font-family: monospace;">'foo'</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'bar'</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'baz'</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'foobar'</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'barbaz'</span><span style="color: #993333; font-family: monospace;">,<br />];</span><br />
<br />
As you can see, PHP arrays are easy to create lists which you can now toss around in your application. But what if you need to reverse the process and remove elments from the end of your array?<br />
<br />
<span style="color: #cc8800; font-family: monospace;">// Removing the last element of an array </span><br />
<span style="color: #6699cc; font-family: monospace;">$last </span><span style="color: #993333; font-family: monospace;">= </span><span style="color: #6699cc; font-family: monospace;">array_pop</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #6699cc; font-family: monospace;">$array</span><span style="color: #993333; font-family: monospace;">);</span><br />
<br />
Now <span style="font-family: Courier New, Courier, monospace;">$last</span> will contain the value "barbaz" and the array itself is now reduced by one from the end.<br />
<br />
<span style="color: #6699cc; font-family: monospace;">$array </span><span style="color: #993333; font-family: monospace;">= [<br /> </span><span style="color: #66cc66; font-family: monospace;">'foo'</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'bar'</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'baz'</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'foobar'</span><span style="color: #993333; font-family: monospace;">,<br />]; </span><br />
<br />
Of course we can also pull elements from the beginning of the array.<br />
<br />
<span style="color: #cc8800; font-family: monospace;">// Removing the first element of an array </span><br />
<span style="color: #6699cc; font-family: monospace;">$first </span><span style="color: #993333; font-family: monospace;">= </span><span style="color: #6699cc; font-family: monospace;">array_shift</span><span style="color: #993333; font-family: monospace;">(</span><span style="color: #6699cc; font-family: monospace;">$array</span><span style="color: #993333; font-family: monospace;">); </span><br />
<br />
Now <span style="font-family: Courier New, Courier, monospace;">$first</span> will contain the value "foo" and the array is now reduced by one from the beginning.<br />
<br />
<span style="color: #6699cc; font-family: monospace;">$array </span><span style="color: #993333; font-family: monospace;">= [<br /> </span><span style="color: #66cc66; font-family: monospace;">'bar'</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'baz'</span><span style="color: #993333; font-family: monospace;">,<br /> </span><span style="color: #66cc66; font-family: monospace;">'foobar'</span><span style="color: #993333; font-family: monospace;">,<br />]; </span><br />
<br />
In our next chapter let's have a look at associative arrays and what you can do with those.<br />
<br />
<br />
<br />
<br />M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com1tag:blogger.com,1999:blog-28215292.post-91131285812166179322016-01-04T11:00:00.000+01:002016-01-04T11:00:14.694+01:00PHP arrays - the basics<br />
<br />
<center>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjG_7XftyeXZbsDBT0Yxz7XD5FvOZyac76Erg1c8MosWJf8Jp438ULBqF5xqPIWnKo0GjqQcDhTPPRsZ8UEc2s-1wxawh0lAxWd99IehFFZaUmWr_yUUt7lsPTjhUerWzKrKslbdQ/s288/iphone_photo.jpg"><img border="0" height="228" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjG_7XftyeXZbsDBT0Yxz7XD5FvOZyac76Erg1c8MosWJf8Jp438ULBqF5xqPIWnKo0GjqQcDhTPPRsZ8UEc2s-1wxawh0lAxWd99IehFFZaUmWr_yUUt7lsPTjhUerWzKrKslbdQ/s400/iphone_photo.jpg" style="margin: 5px;" width="400" /></a></center>
<br />
In 2015 we celebrated the twentieth birthday of PHP and we even had the release of php-7.0.0. Life is all good!<br />
<br />
I wish it was all this peachy. In my work as a consultant or when I'm working on OSS projects I cannot help noticing that some of the basics of PHP are missing, especially when dealing with arrays.<br />
<br />
To give you an example: developers and site owners often complain about their web application being slow. When I get called in to improve performance, I stumble on a huge number of foreach-loops when processing data retrieved from a database. The first iteration happens right at data retrieval where the result set is iterated over to produce a new array of data models.<br />
<br />
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;"><span style="color: #737373;">/**
* Fetches all entries, optionally matching provided conditions,
* optionally ordered by provided order, optionally limited by
* provided number of entries with an optional provided offset.
*
* @param array $where
* @param array $order
* @param int $limit
* @param int $offset
* @return array
*/
public function fetchAll($where = [], $order = [], $limit = 0, $offset = 0)
{
$sql = 'SELECT * FROM ' . $this->getTable();
if ([] !== $where) {
$sql .= ' WHERE ';
$fields = array_keys($where);
$sql .= implode(' AND ', $fields);
}
if ([] !== $order) {
$sql .= ' ORDER BY ' . implode(', ', $order);
}
if (0 < $limit) {
$sql .= ' LIMIT ';
if (0 < $offset) {
$sql .= $offset . ', ';
}
$sql .= $limit;
}
if (false === ($statement = $this->pdo->prepare($sql))) {
$this->error($this->pdo->errorInfo());
}
if (false === $statement->execute(array_values($where))) {
$this->error($statement->errorInfo());
}
$result = $statement->fetchAll(\PDO::FETCH_ASSOC);
$collection = [];
</span><span style="color: red;">foreach ($result as $entry) {
$collection[] = new $this->modelName($entry);
}</span><span style="color: #737373;">
return $collection;
}</span></code></pre>
<br />
A second iteration is often found somewhere at the controller or services level where the collection of data models is enriched or changed as preparation for the view (or output).<br />
<br />
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;"><span style="color: #737373;">/**
* Apply a discount percentage on all articles
*
* @param float $discount
* @return array
*/
public function applyDiscountAsPercentage($discount)
{
$entries = $this->mapper->fetchAll();
$discounts = [];
</span><span style="color: red;">foreach ($entries as $entry) {
$discountProduct = new DiscountProduct($entry->toArray());
$discountCalc = round(($entry->getPrice() * (100 - $discount)) / 100, 2);
$discountProduct->setDiscountPrice($discountCalc);
$discounts[] = $discountProduct;
}</span><span style="color: #737373;">
return $discounts;
}</span></code></pre>
<br />
A third iteration is often found at the output, where the collection is presented in a listing, table or grid.<br />
<br />
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;"><span style="color: #737373;">require_once __DIR__ . '/php_arrays_examples.php';
use \DragonBe\ProductService;
use \DragonBe\ProductMapper;
use \DragonBe\ProductGateway;
$pdo = new \PDO('sqlite:phparray.db');
$productService = new ProductService(new ProductMapper(new ProductGateway($pdo)));
$discounts = $productService->applyDiscountAsPercentage(15);
echo sprintf('%-25s %10s %10s', 'Product', 'Sales', 'Promo') . PHP_EOL;
</span><span style="color: red;">foreach ($discounts as $discountProduct) {
echo sprintf(
'%-25s %10.2f %10.2f',
$discountProduct->getTitle(),
$discountProduct->getPrice(),
$discountProduct->getDiscountPrice()
) . PHP_EOL;
}</span></code></pre>
<br />
At this point, we already count 3 iterations between fetching data and outputting data. Often there are a whole lot more iterations in between. Only to display a simple list of products with discounts.<br />
<br />
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;">Product Sales Promo
demo_phone 295.95 251.56
demo_computer 1999.95 1699.96
demo_tablet 675.00 573.75
demo_drive 5.99 5.09
demo_charger 12.45 10.58
demo_coffee_mug 24.95 21.21
demo_phone_case 29.00 24.65
demo_usb_cable 45.95 39.06
demo_external_screen 199.95 169.96
Added prodcut 129.95 110.46
Added prodcut 129.95 110.46
Added prodcut 129.95 110.46</code></pre>
<br />
So what is the big deal here? Well, in development you probably test these routines with maybe 5 data entries (or 10 for extra edge cases) and performance is great. But in production, especially over time, you're dealing with a couple of thousand records. Millions if you're working for a large company. Simple math will give you an idea how 3 times many will start to slow things down. Unfortunately this is where PHP gets a bad reputation for being slow, even though I see similar mistakes in other technologies as well.<br />
<br />
Luckily PHP has a few powerful array functions to help developers improve performance and their code.<br />
<br />
In next articles I will highlight some of these functions and give real world examples where they will make a difference in performance.<br />
<br />M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com0tag:blogger.com,1999:blog-28215292.post-74009862062678563682015-12-07T19:00:00.000+01:002015-12-08T13:53:05.387+01:00Installing PHP 7 with XDebug, Apache and MySQL on OS X Yosemite<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRGuBkIsb34v65mWjn6LVL-OnsBdeCrvSmm3sxz7syMqRmHnBAAKvjVfXxctKKuVbGK4tpxxYuMpO9N3WRcNBHw1to7cnc_8nx0yzcpPxc8S-Z-rZ6rFNbt92sGeIbPaV0yZcBOA/s1600/Screenshot+2015-12-07+15.26.07.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="171" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRGuBkIsb34v65mWjn6LVL-OnsBdeCrvSmm3sxz7syMqRmHnBAAKvjVfXxctKKuVbGK4tpxxYuMpO9N3WRcNBHw1to7cnc_8nx0yzcpPxc8S-Z-rZ6rFNbt92sGeIbPaV0yZcBOA/s320/Screenshot+2015-12-07+15.26.07.png" width="320" /></a></div>
<br />
In my previous blog post "<a href="http://www.dragonbe.com/2015/12/installing-php-7-on-os-x-yosemite.html" target="_blank">Installing PHP 7 on OS X Yosemite</a>" I gave some insights on how to get quicly started with PHP7 on your Mac, specifically on your commandline. But before I continue on how to make it work with your installed Apache and MySQL I would like to address a subject many people found worth mentioning: PHP Installation Managers.<br />
<br />
<h3>
PHP Installation Managers</h3>
In the feedback I received on my article, people would like to point out that the package managers like "<a href="http://php-osx.liip.ch/" target="_blank">PHP-OSX</a>" binary installer, "<a href="https://github.com/phpenv/phpenv" rel="nofollow" target="_blank">phpenv</a>" multiversion php management and installer, "<a href="https://github.com/phpbrew/phpbrew" rel="nofollow" target="_blank">phpbrew</a>" for installing and running multiple versions of PHP and "<a href="http://brew.sh/" rel="nofollow" target="_blank">HomeBrew</a>" the missing package manger for OS X. There will be probably more tools out there, but these were the suggestions made by some of my readers.<br />
<br />
Again, I have nothing against these tools and I value their functionality a lot. The only reason I posted my article was to show people how you could have PHP 7 run immediately on your system without being too depending of any availability in a package manager or other tool. If you already have one of these PIM's configured, by all means use them. Saves you a bunch of manual work.<br />
<br />
But if you don't have interest to install an additional tool, you can still follow these guidelines to have the latest and greatest PHP7 running on OS X.<br />
<br />
If you would like to keep your system clean, there's also a <a href="http://www.docker.com/" rel="nofollow" target="_blank">Docker</a> installation for PHP7 provided by <a href="http://www.zend.com/" rel="nofollow" target="_blank">Zend Technologies, Inc</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<blockquote class="twitter-tweet" lang="en">
<div dir="ltr" lang="en">
The fastest way to try <a href="https://twitter.com/hashtag/PHP7?src=hash">#PHP7</a>. Use <a href="https://twitter.com/hashtag/Docker?src=hash">#Docker</a> >> docker run zend/php-zendserver:9.0rc9-php7.0GA
<a href="https://twitter.com/hashtag/zray?src=hash">#zray</a> is just a bonus <a href="https://t.co/zhCpZON523">pic.twitter.com/zhCpZON523</a></div>
— Boaz Ziniman (@ziniman) <a href="https://twitter.com/ziniman/status/673802137113989121">December 7, 2015</a></blockquote>
<br />
<h3>
XDebug</h3>
When running PHP you also want to have <a href="http://xdebug.org/" rel="nofollow" target="_blank">XDebug</a> compiled into it. Unfortunately there's not a stable release for XDebug 2.4, but I feel confident using the RC in the mean time as debugging is only something I will use locally.<br />
<br />
Get the latest <a href="http://xdebug.org/download.php" rel="nofollow" target="_blank">XDebug</a> package (at this time of writing it's xdebug-4.2.0RC2), check the signature and unpack it.<br />
<br />
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;">$ cd /tmp/
$ wget http://xdebug.org/files/xdebug-2.4.0rc2.tgz
$ md5check xdebug-2.4.0rc2.tgz e00e92bb2e72f7c94e1300b2a980e79e
OK
$ tar -xvzf xdebug-2.4.0rc2.tgz
$ cd xdebug-2.4.0RC2/</code></pre>
Once done, we need to phpize and configure XDebug using our installed PHP7 in <span style="background-color: #fee9cc; color: rgba(0 , 0 , 0 , 0.74902); font-family: "monaco" , "andale mono" , "courier new" , monospace; font-size: 12px; line-height: 18px;">/opt/php7</span>.<br />
<br />
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;">$ /opt/php7/bin/phpize
$ ./configure --enable-xdebug --with-php-config=/opt/php7/bin/php-config</code></pre>
Now all we need to do is to run <span style="background-color: #fee9cc; color: rgba(0 , 0 , 0 , 0.74902); font-family: "monaco" , "andale mono" , "courier new" , monospace; font-size: 12px; line-height: 18px;">make</span> and <span style="background-color: #fee9cc; color: rgba(0 , 0 , 0 , 0.74902); font-family: "monaco" , "andale mono" , "courier new" , monospace; font-size: 12px; line-height: 18px;">make test</span> to complete the build. This will create a <span style="background-color: #fee9cc; color: rgba(0 , 0 , 0 , 0.74902); font-family: "monaco" , "andale mono" , "courier new" , monospace; font-size: 12px; line-height: 18px;">xdebug.so</span> shared object we need to copy to our PHP7 installation extension directory.<br />
<br />
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;">$ sudo cp modules/xdebug.so /opt/php7/lib/php/extensions/no-debug-non-zts-20151012/</code></pre>
Now we have the extension installed, we need to inform PHP7 we have the extension available. In the configuration of PHP7 in my previous article, I had stated that our configuration was going to be installed in <span style="background-color: #fee9cc; color: rgba(0 , 0 , 0 , 0.74902); font-family: "monaco" , "andale mono" , "courier new" , monospace; font-size: 12px; line-height: 18px;">/etc/php7</span> (see <span style="background-color: #fee9cc; color: rgba(0 , 0 , 0 , 0.74902); font-family: "monaco" , "andale mono" , "courier new" , monospace; font-size: 12px; line-height: 18px;">--with-config-file-path=/etc/${PHP}</span> argument). This also means we need to ensure a <span style="background-color: #fee9cc; color: rgba(0 , 0 , 0 , 0.74902); font-family: "monaco" , "andale mono" , "courier new" , monospace; font-size: 12px; line-height: 18px;">php.ini</span> file is there. Since this is a clean installation, we can easily copy the supplied <span style="background-color: #fee9cc; color: rgba(0 , 0 , 0 , 0.74902); font-family: "monaco" , "andale mono" , "courier new" , monospace; font-size: 12px; line-height: 18px;">php.ini-development</span> into our configration path.<br />
<br />
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;">$ sudo cp /tmp/php-7.0.0/php.ini-development /etc/php7/php.ini</code></pre>
Now we need to add the xdebug configuration in it.<br />
<br />
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;">[xdebug]
zend_extension=/opt/php7/lib/php/extensions/no-debug-non-zts-20151012/xdebug.so</code></pre>
When we now run php -v on the commandline, we now see xdebug is installed correctly.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinwx3M6DAwIofCxtgQEjVepAgawW0GsgQgYkXRm7NIaA_kyymx6TmpQ_VcNRzxNQOwrV29-_-JAA0cTs80sioNkzr2On4wGU2ifzAglRQXs27Y0A-fEwv9PTf-qoNJzHjiPhEtJw/s1600/Screenshot+2015-12-07+14.32.09.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="303" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinwx3M6DAwIofCxtgQEjVepAgawW0GsgQgYkXRm7NIaA_kyymx6TmpQ_VcNRzxNQOwrV29-_-JAA0cTs80sioNkzr2On4wGU2ifzAglRQXs27Y0A-fEwv9PTf-qoNJzHjiPhEtJw/s400/Screenshot+2015-12-07+14.32.09.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<h3>
Further php.ini settings</h3>
In PHP7 if you omit to change the <span style="background-color: #fee9cc; color: rgba(0 , 0 , 0 , 0.74902); font-family: "monaco" , "andale mono" , "courier new" , monospace; font-size: 12px; line-height: 18px;">date.timezone</span>, it will be set to UTC <b>by default</b> which might cause some conflicts if you have time and date operations. Best is you set it to the timezone you prefer (e.g. Europe/Brussels).<br />
<br />
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;">[Date]
; Defines the default timezone used by the date functions
; http://php.net/date.timezone
date.timezone = Europe/Brussels</code></pre>
<br />
<h3>
Apache Module for PHP7</h3>
OS X Yosemite comes with Apache 2.4 installed, so all we need to do is ensure PHP7 is compiled with flag <span style="background-color: #fee9cc; color: rgba(0 , 0 , 0 , 0.74902); font-family: "monaco" , "andale mono" , "courier new" , monospace; font-size: 12px; line-height: 18px;">--with-apxs2</span> enabled, which we already provided in my configure script mentioned in <a href="http://www.dragonbe.com/2015/12/installing-php-7-on-os-x-yosemite.html" target="_blank">my previous article</a>. This will modify our Apache <span style="background-color: #fee9cc; color: rgba(0 , 0 , 0 , 0.74902); font-family: "monaco" , "andale mono" , "courier new" , monospace; font-size: 12px; line-height: 18px;">/etc/apache2/httpd.conf</span> and will add the following line:<br />
<br />
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;">LoadModule php7_module libexec/apache2/libphp7.so</code></pre>
So now we have a PHP5 and a PHP7 module in our configuration. Prefer to uncoment the line for loading the PHP5 module so we only have the PHP7 module to take care of.<br />
<br />
Now you just have to make the configuration for <span style="background-color: #fee9cc; color: rgba(0 , 0 , 0 , 0.74902); font-family: "monaco" , "andale mono" , "courier new" , monospace; font-size: 12px; line-height: 18px;">php7_module</span> available. Therefor I added a new file <span style="background-color: #fee9cc; color: rgba(0 , 0 , 0 , 0.74902); font-family: "monaco" , "andale mono" , "courier new" , monospace; font-size: 12px; line-height: 18px;">/etc/apache2/other/php7.conf</span> where I have specific PHP7 directives (comparable to the PHP5 directives).<br />
<br />
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><pre style='color:#000000;background:#ffffff;'><span style='color:#7f9fbf; font-weight:bold; '><IfModule php7_module></span>
AddType application/x<span style='color:#0000e6; '>-httpd-</span>php .php
AddType application/x<span style='color:#0000e6; '>-httpd-</span>php-source .phps
<span style='color:#7f9fbf; font-weight:bold; '> <IfModule dir_module></span>
DirectoryIndex index.html index.php
<span style='color:#7f9fbf; font-weight:bold; '> </IfModule></span>
<span style='color:#7f9fbf; font-weight:bold; '></IfModule></span>
</pre></pre>
Now we can restart Apache and we should be able to see a nice <span style="background-color: #fee9cc; color: rgba(0 , 0 , 0 , 0.74902); font-family: "monaco" , "andale mono" , "courier new" , monospace; font-size: 12px; line-height: 18px;">phpinfo()</span> page for PHP7 (I always have one available in the webroot).<br />
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiHwK4kXSVbaFr4PNJqHdzAvFvRGQsRkztBg2cvgaDfFjT_ooPW39ZMcUKzk4GSp-7PFCbUUBa4e0PxVs8SbxgvbKBskoPgZTCK797Ip_CyOOt7t7pETlEyf5G8Jw9PXwvyCDDqA/s1600/Screenshot+2015-12-04+15.09.34.png" imageanchor="1"><img border="0" height="252" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiHwK4kXSVbaFr4PNJqHdzAvFvRGQsRkztBg2cvgaDfFjT_ooPW39ZMcUKzk4GSp-7PFCbUUBa4e0PxVs8SbxgvbKBskoPgZTCK797Ip_CyOOt7t7pETlEyf5G8Jw9PXwvyCDDqA/s400/Screenshot+2015-12-04+15.09.34.png" width="400" /></a></div>
<div style="text-align: left;">
Success! We have now PHP7 for our web applications too.</div>
<br />
<h3>
MySQL setup</h3>
The final step is to ensure we can connect with the installed MySQL database. Since we already took care of that in our <span style="background-color: #fee9cc; color: rgba(0 , 0 , 0 , 0.74902); font-family: "monaco" , "andale mono" , "courier new" , monospace; font-size: 12px; line-height: 18px;">configure-php.sh</span> script, all database settings were already configured. No further settings are required.<br />
<br />
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;">--with-mysqli \
--with-pdo-mysql \
--with-mysql-sock=/tmp/mysql.sock</code></pre>
Done. That's it. Again, if you can work with a package manager of binary installer tool, go ahead use them. If you would like to have a bit more control, feel free to use this guide.M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com0tag:blogger.com,1999:blog-28215292.post-75396295186340809752015-12-05T01:42:00.000+01:002015-12-05T01:42:07.644+01:00Installing PHP 7 on OS X Yosemite<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.nolifeclub.org/wp-content/uploads/2014/07/OS-X-Yosemite.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://www.nolifeclub.org/wp-content/uploads/2014/07/OS-X-Yosemite.png" height="223" width="400" /></a></div>
Yesterday was <a href="http://php.net/archive/2015.php#id2015-12-03-1" rel="nofollow" target="_blank">the release of PHP7.0.0</a> and I wanted to have it on my mac as fast as possible. Since I'm still using Mac OS X Yosemite I will post here the steps to upgrade my platform, it might be useful for you too.<br />
<br />
<h3>
Requirements</h3>
Since Apple is doing a great job to provide PHP, Apache and MySQL straight out of the box, I'm not worrying about the Apache and MySQL.<br />
<br />
In order to to install PHP from source, you need to have <a href="https://www.dropbox.com/s/09j02jgx8ktbtrm/Screenshot%202015-12-05%2000.05.51.png?dl=0" rel="nofollow" target="_blank">XCode</a> installed as it provides required libraries and headers that you will need to have a successful experience.<br />
<div style="text-align: center;">
<a href="https://itunes.apple.com/us/app/xcode/id497799835?mt=12" rel="nofollow" target="_blank"><span id="goog_1308301662"></span><span id="goog_1308301663"></span><img border="0" height="253" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcOi425v34FymvAj-hkiLLx6QQLOVsTdis7SId5m4srz5kI2sc9Jk_RnfjrfLnyrteal2sL3MIm3t41OQITAFNuxqFw_f_J_C__Hk91P-ex8d4Rwc3md7XS6YibFFPlAcD8f_nig/s400/xcode_download.png" width="400" /></a></div>
Of course, get the latest and greatest PHP7.0.0 bundle straight from <a href="http://php.net/downloads.php" rel="nofollow" target="_blank">php.net</a>. Don't forget to verify the signatures before you get started unpacking the sources.<br />
<br />
<h3>
Time to bake the sources</h3>
I like to build my apps from sources, even though there are package managers that will do it in a single command. There are really some great benefits from building from sources:<br />
<br />
<ul>
<li>You can switch on and off modules as you go</li>
<li>You can now choose how you want to run PHP (as module, cgi or fpm)</li>
<li>You can enable extra debugging and profiling features</li>
<li>And my favorite: you can automate it</li>
</ul>
<div>
When you've unpacked the bundle (let's say its in <span style="background-color: #fee9cc; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; line-height: 18px;">/tmp</span>) go into the directory <span style="background-color: #fee9cc; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; line-height: 18px;">/tmp/php-7.0.0</span>. Here you will find your master command <span style="background-color: #fee9cc; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; line-height: 18px;">configure</span> that you will need to set up your PHP installation. When you're requiring to know what options you can use, <span style="background-color: #fee9cc; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; line-height: 18px;">configure --help|less</span> is your friend.</div>
<div>
<br /></div>
<div>
For my own convenience, I've created a little tool that helps me to configure any version of PHP as it sets the bare minimum I need to achieve a running PHP platform.</div>
<div>
<br /></div>
<br />
<pre style="-webkit-print-color-adjust: exact; background-color: white; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;">#!/bin/sh
PHP=$1
if [ -t $PHP ]; then
echo "Usage: $0 <prefix>"
echo " prefix A prefix for your installation you would like to use"
echo " e.g. 'php7', 'php56'"
exit 0
fi
XCODE_PATH=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/
LIB_PATH=/usr
./configure \
--prefix=/opt/${PHP} \
--enable-cli \
--with-apxs2 \
--with-iconv=${LIB_PATH} \
--with-config-file-path=/etc/${PHP} \
--with-config-file-scan-dir=/Library/Server/Web/Config/php \
--with-libxml-dir=${XCODE_PATH} \
--with-openssl=/usr \
--with-mysqli \
--with-pdo-mysql \
--with-mysql-sock=/tmp/mysql.sock</prefix></code></pre>
<div>
</div>
<br />
<div>
I made this script (<span style="background-color: #fee9cc; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; line-height: 18px;">configure-php.sh</span>) executable with <span style="background-color: #fee9cc; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; line-height: 18px;">chmod +x configure-php.sh</span>. All that's required is to pick a great prefix (where you want php to be installed) and with <span style="background-color: #fee9cc; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; line-height: 18px;">./configure-php.sh /opt/php7</span> you start configuring PHP.</div>
<div>
<br /></div>
<div>
Once your process is completed (and you don't get errors), it's time to run <span style="background-color: #fee9cc; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; line-height: 18px;">make</span>, <span style="background-color: #fee9cc; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; line-height: 18px;">make test</span> and <span style="background-color: #fee9cc; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; line-height: 18px;">make install</span>.</div>
<div>
<br /></div>
<h3>
Let's check it out</h3>
<div>
Now it's time to check if we have a working PHP. Let's find out with <span style="background-color: #fee9cc; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; line-height: 18px;">/opt/php7/bin/php -v</span> and you should be getting something like this.</div>
<div>
<br /></div>
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6aJNo2ZLlDccJ4qntVxrInd75VJN0rHi4czqWWYKk4HdzlyYzmZJowJx3Ml4FwQ1dkgV8-WnZx0jaxwgAYIX1-grCkxWMjdvQ5fck91pwsXXmSWseXhDejGqsAm6pyl18TUDHqw/s1600/Screenshot+2015-12-05+01.37.58.png" imageanchor="1"><img border="0" height="305" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6aJNo2ZLlDccJ4qntVxrInd75VJN0rHi4czqWWYKk4HdzlyYzmZJowJx3Ml4FwQ1dkgV8-WnZx0jaxwgAYIX1-grCkxWMjdvQ5fck91pwsXXmSWseXhDejGqsAm6pyl18TUDHqw/s400/Screenshot+2015-12-05+01.37.58.png" width="400" /></a></div>
<div>
<br /></div>
<div>
In a next article I will explain hot to add xdebug and have PHP7 run as an Apache module in the existing Mac OS environment. Until then.</div>
<div>
<br /></div>
<br />
<br />M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com0tag:blogger.com,1999:blog-28215292.post-63846657682746557142015-07-26T16:14:00.000+02:002015-07-27T13:09:20.100+02:00Speeding up database calls with PDO and iterators<div style="text-align: left;">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEid_z2swTJjMEF0H0VbGGrt4iT7IxML-tGYMyO95UNk84r5ibSgpBElNICUaNqB4GCWiUnOs2CJfqbOu_DIImzPMAlLwd380hmOsKQKOBTnjsbFWc-7ApsADIFHaSU41VHaz0pKyg/s1600/FA-18_Hornet_breaking_sound_barrier_%25287_July_1999%2529_-_filtered.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEid_z2swTJjMEF0H0VbGGrt4iT7IxML-tGYMyO95UNk84r5ibSgpBElNICUaNqB4GCWiUnOs2CJfqbOu_DIImzPMAlLwd380hmOsKQKOBTnjsbFWc-7ApsADIFHaSU41VHaz0pKyg/s1600/FA-18_Hornet_breaking_sound_barrier_%25287_July_1999%2529_-_filtered.jpg" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Image source: <a href="https://en.wikipedia.org/wiki/Supersonic_speed" rel="nofollow" target="_blank">Wikipedia.org</a></td></tr>
</tbody></table>
When you review lots of code, you often wonder why things were written the way they were. Especially when making expensive calls to a database, I still see things that could and should be improved.<br />
<h2>
No framework development</h2>
When working with a framework, mostly these database calls are optimized for the developer and abstract the complex logic to improve and optimize the retrieval and usage of data. But then developers need to build something without a framework and end up using the basics of <a href="https://secure.php.net/" rel="nofollow" target="_blank">PHP</a> in a sub-optimal way.<br />
<br />
<pre style="-webkit-print-color-adjust: exact; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; background-color: white; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;">$pdo = new \PDO(
$config['db']['dsn'],
$config['db']['username'],
$config['db']['password']
);
$sql = 'SELECT * FROM `gen_contact` ORDER BY `contact_modified` DESC';
$stmt = $pdo->prepare($sql);
$stmt->execute();
$data = $stmt->fetchAll(\PDO::FETCH_OBJ);
echo 'Getting the contacts that changed the last 3 months' . PHP_EOL;
foreach ($data as $row) {
$dt = new \DateTime('2015-04-01 00:00:00');
if ($dt->format('Y-m-d') . '00:00:00' < $row->contact_modified) {
echo sprintf(
'%s (%s)| modified %s',
$row->contact_name,
$row->contact_email,
$row->contact_modified
) . PHP_EOL;
}
}</code></pre>
Above example code is a most common way to retrieve data. At first sight, this code is clean and looks good, but looking more closely you will discover a couple of points to improve.<br />
<br />
<ul>
<li>Above code is not reusable, so whenever you need a similar functionality you're stuck with duplicating existing code.</li>
<li>Even though you're fetching an object with <span style="background-color: #fee9cc; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; line-height: 18px;">$stmt->fetchAll(\PDO::FETCH_OBJ);</span> you still face the issue you're using an array of objects which will consume too much memory when fetching lots of data.</li>
<li>Filtering is done within the routine, which also means that if you have other filtering conditions you need to modify existing logic, making it hard for maintenance and expanding functionality.</li>
</ul>
<h2>
Iterators</h2>
<div>
Most of the modern frameworks are using Iterators for their data retrieval, because they're fast and reusable. But also they allow other Iterators to filter and modify the retrieved results. Building an application without a framework still gives you the option to use Iterators as they're part of <a href="https://secure.php.net/" rel="nofollow" target="_blank">PHP</a> since <a href="http://php.net/ChangeLog-5.php" rel="nofollow" target="_blank">Version 5.0.0 Beta 2</a>.</div>
<div>
<br /></div>
<div>
So lets assume you continue to use <a href="http://php.net/PDO" rel="nofollow" target="_blank">PDO</a> for your data retrieval, we can choose between two options:</div>
<div>
<ol>
<li>Use <span style="background-color: #fee9cc; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; line-height: 18px;">PDOStatement::fetchAll()</span> to retrieve all data in a single go</li>
<li>Use <span style="background-color: #fee9cc; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; line-height: 18px;">PDOSTatement::fetch()</span> to retrieve a single row per iteration</li>
</ol>
<div>
Even though the first option seems really tempting, I prefer to use option two as it allows me to create a single Iterator to do the retrieval for me without limiting myself to options required to make the query (and thus making it reusable for any kind of retrievals).<br />
<br />
<pre style="-webkit-print-color-adjust: exact; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; background-color: white; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;"><?php
/**
* Class DbRowIterator
*
* File: Iterator/DbRowIterator.php
*/
class DbRowIterator implements Iterator
{
/** @var \PDOStatement $pdoStatement The PDO Statement to execute */
protected $pdoStatement;
/** @var int $key The cursor pointer */
protected $key;
/** @var bool|\stdClass The resultset for a single row */
protected $result;
/** @var bool $valid Flag indicating there's a valid resource or not */
protected $valid;
public function __construct(\PDOStatement $PDOStatement)
{
$this->pdoStatement = $PDOStatement;
}
/**
* @inheritDoc
*/
public function current()
{
return $this->result;
}
/**
* @inheritDoc
*/
public function next()
{
$this->key++;
$this->result = $this->pdoStatement->fetch(
\PDO::FETCH_OBJ,
\PDO::FETCH_ORI_ABS,
$this->key
);
if (false === $this->result) {
$this->valid = false;
return null;
}
}
/**
* @inheritDoc
*/
public function key()
{
return $this->key;
}
/**
* @inheritDoc
*/
public function valid()
{
return $this->valid;
}
/**
* @inheritDoc
*/
public function rewind()
{
$this->key = 0;
}
}</code></pre>
Above Iterator is just implementing the <a href="http://php.net/manual/en/class.iterator.php" rel="nofollow" target="_blank">PHP Iterator interface</a>, but in our example this is more than enough to achieve our goal.</div>
</div>
<div>
<br /></div>
<div>
As you can see, we implement the logic for data retrieval in the "next" loop, as this is our forward retrieval sequence. Take note of the second and third argument of <span style="background-color: #fee9cc; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; line-height: 18px;">PDOSTatement::fetch()</span> statement: with the second argument we can control the cursor in our data retrieval, the third argument is to position the cursor for this data retrieval which was set scrollable outside the Iterator.</div>
<div>
<br /></div>
<div>
<pre style="-webkit-print-color-adjust: exact; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; background-color: white; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;"><?php
class LastPeriodIterator extends FilterIterator
{
protected $period;
public function __construct(\Iterator $iterator, $period = 'last week')
{
parent::__construct($iterator);
$this->period = $period;
}
public function accept()
{
if (!$this->getInnerIterator()->valid()) {
return false;
}
$row = $this->getInnerIterator()->current();
$dt = new \DateTime($this->period);
if ($dt->format('Y-m-d') . '00:00:00' < $row->contact_modified) {
return true;
}
return false;
}
}</code></pre>
</div>
<div>
For filtering our data, we can now extend the <a href="http://php.net/manual/en/class.filteriterator.php" rel="nofollow" target="_blank">SPL FilterIterator</a> that will allow us to attach our filtering immediately to our <i>DbRowIterator</i>, making it extendable and reusable immediately.</div>
<div>
<br /></div>
<div>
Changing our initial data retrieval code into code that will use both of our Iterators is now very simple:</div>
<div>
<br /></div>
<div>
<pre style="-webkit-print-color-adjust: exact; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; background-color: white; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;">$pdo = new \PDO(
$config['db']['dsn'],
$config['db']['username'],
$config['db']['password']
);
$sql = 'SELECT * FROM `gen_contact` ORDER BY `contact_modified` DESC';
$stmt = $pdo->prepare($sql, [\PDO::ATTR_CURSOR => \PDO::CURSOR_SCROLL]);
$stmt->execute();
$data = new DbRowIterator($stmt);
echo 'Getting the contacts that changed the last 3 months' . PHP_EOL;
$lastPeriod = new LastPeriodIterator($data, '2015-04-01 00:00:00');
foreach ($lastPeriod as $row) {
echo sprintf(
'%s (%s)| modified %s',
$row->contact_name,
$row->contact_email,
$row->contact_modified
) . PHP_EOL;
}</code></pre>
</div>
<div>
Please pay attention to <span style="background-color: #fee9cc; color: rgba(0, 0, 0, 0.74902); font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 12px; line-height: 18px;">$pdo->prepare($sql, [\PDO::ATTR_CURSOR => \PDO::CURSOR_SCROLL]);</span> as we now need to ensure the cursor of dataretrieval is now scrollable so we can use row by row control.</div>
<h2>
Benchmarking</h2>
<div>
I know that all this requires a bit of "extra" work and you might wonder why you should invest this "more work" as the foreach-loop was working as well. Let me show you with a benchmark between the two:</div>
<h3>
Foreach loop</h3>
<div>
<ul>
<li>Data fetching time for 63992 of 250000 records: 2.14 seconds</li>
<li>Data processing time for 63992 of 250000 records: 7.11 seconds</li>
<li>Total time for 63992 of 250000 records: 9.25 seconds</li>
<li>Memory consumption for 63992 of 250000 records: 217.75MB</li>
</ul>
<h3>
Iterator loop</h3>
</div>
<div>
<ul>
<li>Data fetching time for 63992 of 250000 records: 0.92 seconds</li>
<li>Data processing time for 63992 of 250000 records: 5.57 seconds</li>
<li>Total time for 63992 of 250000 records: 6.49 seconds</li>
<li>Memory consumption for 63992 of 250000 records: 0.25MB</li>
</ul>
<h3>
Result of this benchmark</h3>
</div>
<div>
<ul>
<li>Data retrieval is faster with Iterators</li>
<li>Data processing is faster with Iterators</li>
<li>Memory consumption is enormously better with Iterators</li>
</ul>
<i>Benchmark executed with MySQL 5.5.43 and PHP 5.5.26 on Ubuntu 12.04 LTS (virtual machine). Other versions of PHP, Mysql or OS might give you different results. 250000 records generated using <a href="https://github.com/fzaninotto/Faker" rel="nofollow" target="_blank">fzaninotto/Faker</a>.</i><br />
<h2>
Conclusion</h2>
</div>
<div>
Using simple Iterators in your PHP code you can speed up the data retrieval and processing, but the most important thing that this benchmark shows you is that Iterators will save a ton of memory.</div>
<h3>
Sidenote</h3>
<div>
Iterators are more effective for processing large amounts of data. For small amounts of data (aproximately under 5000 entries) Iterators might be even slower than using arrays, but you will still be winning on memory though.</div>
M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com7tag:blogger.com,1999:blog-28215292.post-32276378065005225932015-06-08T19:30:00.000+02:002015-06-08T21:14:53.210+02:0020 years of php<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaDLN5FcD8eUZMU0y4djLzQDDdq-hoZQWBLgNorMjjavqFpAJ_je-dkWq8JFMpxFR06zj651fKs7mcWGeldvwajToW6bDwIjRdDalFlTXE212_vnfG-SwgSMANPcgmW0o5DFnK1g/s1600/20_years_of_php_golden_elephpant_edited.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="155" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaDLN5FcD8eUZMU0y4djLzQDDdq-hoZQWBLgNorMjjavqFpAJ_je-dkWq8JFMpxFR06zj651fKs7mcWGeldvwajToW6bDwIjRdDalFlTXE212_vnfG-SwgSMANPcgmW0o5DFnK1g/s400/20_years_of_php_golden_elephpant_edited.jpg" width="400" /></a></div>
<br />
<h1 style="-webkit-print-color-adjust: exact; color: #404040; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 30px; line-height: 36px; margin: 0px 0px 18px; padding: 0px;">
</h1>
<div style="-webkit-print-color-adjust: exact; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; line-height: 18px; margin-bottom: 9px; padding: 0px;">
On June 8, 1995 <a href="https://groups.google.com/forum/#!msg/comp.infosystems.www.authoring.cgi/PyJ25gZ6z7A/M9FkTUVDfcwJ" style="-webkit-print-color-adjust: exact; color: #0069d6;">Rasmus Lerdorf open-sourced the code for his "Personal Homepage"</a> and posted it to the news group comp.infosystems.www.authoring.cgi. Yes, NNTP was hot and famous back in those days! And because <a href="http://benramsey.com/blog/2015/06/20-years-of-php/" style="-webkit-print-color-adjust: exact; color: #0069d6;">Ben Ramsey asked everyone in the PHP community to tell their PHP story</a>, I felt it was time to share mine.<br />
<br /></div>
<div style="-webkit-print-color-adjust: exact; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; line-height: 18px; margin-bottom: 9px; padding: 0px;">
For me, my PHP story begins 6 years after Rasmus published his source code for PHP. In 2001 I started as System Engineer at <a href="http://www.telenet.be/" style="-webkit-print-color-adjust: exact; color: #0069d6;">Telenet</a>, a cable internet provider in Belgium, where they were looking for someone to develop and maintain their website in PHP. I had worked as Perl developer in the past and found the change to PHP relatively easy.</div>
<div style="-webkit-print-color-adjust: exact; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; line-height: 18px; margin-bottom: 9px; padding: 0px;">
In 2005 I started off as a freelancer working as PHP developer and worked at several positions in big enterprises and government agencies.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://amzn.to/1dXP7dJ" style="-webkit-print-color-adjust: exact; color: #0069d6; margin-left: 1em; margin-right: 1em;"><img alt="PHPUnit Pocket Guide" src="http://blob.phpdev.nu/dragonbe/phpunit_pocket_guide.jpg" height="320" style="-webkit-print-color-adjust: exact; border: none;" width="194" /></a></div>
<div style="-webkit-print-color-adjust: exact; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; line-height: 18px; margin-bottom: 9px; padding: 0px;">
</div>
<div style="-webkit-print-color-adjust: exact; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; line-height: 18px; margin-bottom: 9px; padding: 0px;">
In 2006 I was introduced to PHPUnit, thanks to <a href="http://amzn.to/1dXP7dJ" style="-webkit-print-color-adjust: exact; color: #0069d6;">Sebastian Bergmann's PHPUnit Pocket Guide</a> which seemed like a very smart way to test your applications. So that's when I started writing unit tests for the first time and never stopped writing them.</div>
<div style="-webkit-print-color-adjust: exact; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; line-height: 18px; margin-bottom: 9px; padding: 0px;">
After working with PHP for 5 years, I was doubting if I was doing a good job as there was not much to compare with. So in 2006 I got <a href="http://www.zend.com/en/yellow-pages/ZEND004628" style="-webkit-print-color-adjust: exact; color: #0069d6;">Zend Certified for PHP 4</a> which opened up a whole new world to me. As Zend Certified Engineer (ZCE) I received an invite from <a href="http://www.zend.com/" style="-webkit-print-color-adjust: exact; color: #0069d6;">Zend</a> to join their biggest PHP event of the year:<a href="http://www.zendcon.com/" style="-webkit-print-color-adjust: exact; color: #0069d6;">ZendCon 2007</a>. So I saved up all that I could spare and booked my flight, ticket and hotel stay.</div>
<div style="-webkit-print-color-adjust: exact; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; line-height: 18px; margin-bottom: 9px; padding: 0px;">
At <a href="http://www.zendcon.com/" style="-webkit-print-color-adjust: exact; color: #0069d6;">ZendCon</a> I was introduced to "The PHP Community" through the <a href="https://www.flickr.com/photos/calevans/sets/72157602648775566" style="-webkit-print-color-adjust: exact; color: #0069d6;">Zend Trading Cards</a> which was a brilliant idea to introduce the "community" to newcomers in the community. And I met <a href="http://blog.calevans.com/" style="-webkit-print-color-adjust: exact; color: #0069d6;">Mr. Cal Evans</a>, who in his gentle voice and everlasting smile said "I was the one" to form a community myself in my own region. The last day of ZendCon, I got a phone call from my wife at 2am saying we were expecting a baby! That was probably the wildest night for me at ZendCon.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://plopster.blob.core.windows.net/dragonbe/xander_friedel_michelangelo.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://plopster.blob.core.windows.net/dragonbe/xander_friedel_michelangelo.jpg" height="242" width="320" /></a></div>
<div style="-webkit-print-color-adjust: exact; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; line-height: 18px; margin-bottom: 9px; padding: 0px;">
<br /></div>
<div style="-webkit-print-color-adjust: exact; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; line-height: 18px; margin-bottom: 9px; padding: 0px;">
</div>
<div style="-webkit-print-color-adjust: exact; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; line-height: 18px; margin-bottom: 9px; padding: 0px;">
On June 8, 2008 my wife gave birth to our son Xander. Another sign that PHP would have a major impact on my life.</div>
<div style="-webkit-print-color-adjust: exact; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; line-height: 18px; margin-bottom: 9px; padding: 0px;">
Together with the help of <a href="https://www.onename.io/felixdv" style="-webkit-print-color-adjust: exact; color: #0069d6;">Felix De Vliegher</a> we started <a href="http://www.phpbelgium.com/" style="-webkit-print-color-adjust: exact; color: #0069d6;">PHPBelgium</a>. Later on we joined forces with the Dutch PHP user group <a href="http://www.phpgg.nl/" style="-webkit-print-color-adjust: exact; color: #0069d6;">phpGG</a> and formed <a href="http://www.phpbenelux.eu/" style="-webkit-print-color-adjust: exact; color: #0069d6;">PHPBenelux</a>.</div>
<div style="-webkit-print-color-adjust: exact; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; line-height: 18px; margin-bottom: 9px; padding: 0px;">
In 2009 my wife and I founded <a href="http://www.in2it.be/" style="-webkit-print-color-adjust: exact; color: #0069d6;">in2it</a> where I would be doing the same thing as I was already doing: providing professional PHP consulting services to businesses, giving professional training courses and coach development teams to improve the way they develop PHP applications. My wife took over the graphical design part and together we have lifted the company into a known brand for web application development and design.</div>
<div style="-webkit-print-color-adjust: exact; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; line-height: 18px; margin-bottom: 9px; padding: 0px;">
In that same year I was asked to speak at <a href="http://phpconference.nl/" style="-webkit-print-color-adjust: exact; color: #0069d6;">Dutch PHP Conference</a> about <a href="http://www.php.net/spl" style="-webkit-print-color-adjust: exact; color: #0069d6;">SPL</a>. Since that first talk I've spoken at <a href="https://joind.in/user/view/19" style="-webkit-print-color-adjust: exact; color: #0069d6;">several conferences in the world</a> and attended even more.</div>
<div style="-webkit-print-color-adjust: exact; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; line-height: 18px; margin-bottom: 9px; padding: 0px;">
In 2010 our second son Ares was born during <a href="http://devzone.zend.com/1751/twice-the-amount-of-bugs-and-twice-the-amount-of-winners/" style="-webkit-print-color-adjust: exact; color: #0069d6;">Zend Framework bug hunt days</a> on July 18 and our third son Tycho was born just before PHPBenelux Conference 2013. So yes, all our sons have PHP-ness since their births.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://plopster.blob.core.windows.net/dragonbe/tycho_ares_xander.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://plopster.blob.core.windows.net/dragonbe/tycho_ares_xander.jpg" height="240" width="320" /></a></div>
<div style="-webkit-print-color-adjust: exact; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; line-height: 18px; margin-bottom: 9px; padding: 0px;">
<br /></div>
<div style="-webkit-print-color-adjust: exact; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; line-height: 18px; margin-bottom: 9px; padding: 0px;">
</div>
<div style="-webkit-print-color-adjust: exact; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; line-height: 18px; margin-bottom: 9px; padding: 0px;">
Yes, PHP has given me a basis to earn a good living, pay my bills and support my family. But it also has given me the PHP community: A big, welcoming group of people who I call my distant family. And all thanks to <a href="http://blog.calevans.com/" style="-webkit-print-color-adjust: exact; color: #0069d6;">Mr. Cal Evans</a>, the Godfather of the <a href="http://phpcommunity.org/" style="-webkit-print-color-adjust: exact; color: #0069d6;">PHP Community</a>.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.flickr.com/photos/calevans/1716613682/" style="-webkit-print-color-adjust: exact; color: #0069d6; margin-left: 1em; margin-right: 1em;"><img alt="PHP Godfather" src="http://farm3.staticflickr.com/2246/1716613682_7032a2f27b_z.jpg?zz=1" height="320" style="-webkit-print-color-adjust: exact; border: none;" width="228" /></a></div>
<div style="-webkit-print-color-adjust: exact; color: #737373; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; font-size: 13px; line-height: 18px; margin-bottom: 9px; padding: 0px;">
</div>
M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com0tag:blogger.com,1999:blog-28215292.post-70112232977313623592015-05-27T00:37:00.000+02:002015-05-27T00:37:16.878+02:00Little things can make a difference<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://farm6.staticflickr.com/5165/5350787982_fa7ee73975_o.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="265" src="https://farm6.staticflickr.com/5165/5350787982_fa7ee73975_o.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Source: <a href="https://www.flickr.com/photos/theleticiabertin/5350787982" rel="nofollow" target="_blank">theleticiabertin on Flickr.com</a></td></tr>
</tbody></table>
<br />
Wow, I never expected this much involvement when I created <a href="http://in2.se/1IZ41gy" rel="nofollow" target="_blank">an overview of upcoming conferences this fall</a>. I cannot deny I love Markdown to write simple things and I love simplicity. I use <a href="http://iawriter.com/" rel="nofollow" target="_blank">IA Writer</a> to have distraction-free editing power on both my phone and laptop.<br />
<br />
<div class="c-info__img-wrap c-info__img-wrap--tile" style="background-color: white; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; border: 1px solid rgb(220, 220, 220); color: #666666; display: table-cell; float: left; font-family: DDG_ProximaNova, DDG_ProximaNova_UI_0, DDG_ProximaNova_UI_1, DDG_ProximaNova_UI_2, DDG_ProximaNova_UI_3, DDG_ProximaNova_UI_4, DDG_ProximaNova_UI_5, DDG_ProximaNova_UI_6, 'Proxima Nova', 'Helvetica Neue', Helvetica, 'Segoe UI', 'Nimbus Sans L', 'Liberation Sans', 'Open Sans', FreeSans, Arial, sans-serif; font-size: 14px; height: 150px; left: 0px; line-height: 150px; margin: 0px; max-width: 220px; overflow: hidden; padding: 0px 15px; position: relative; text-align: center; top: 0px; vertical-align: top;">
<a class="c-info__img-wrap__in" href="https://en.wikipedia.org/wiki/iA_Writer" style="border: 0px; color: #6d59a3; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration: none; vertical-align: baseline;"><img class="c-info__img js-sized-img" src="https://duckduckgo.com/i/c8455ed1.png" style="border: none; display: inline; font-family: inherit; font-style: inherit; font-variant: inherit; height: auto; line-height: inherit; margin: 0px; max-height: 120px; max-width: 220px; min-width: 1px; padding: 0px; position: relative; vertical-align: middle; width: auto;" /></a></div>
<div class="c-info__body" style="border: 0px; color: #666666; font-family: DDG_ProximaNova, DDG_ProximaNova_UI_0, DDG_ProximaNova_UI_1, DDG_ProximaNova_UI_2, DDG_ProximaNova_UI_3, DDG_ProximaNova_UI_4, DDG_ProximaNova_UI_5, DDG_ProximaNova_UI_6, 'Proxima Nova', 'Helvetica Neue', Helvetica, 'Segoe UI', 'Nimbus Sans L', 'Liberation Sans', 'Open Sans', FreeSans, Arial, sans-serif; font-size: 14px; line-height: 19px; margin: 0px; overflow: hidden; padding: 0.35em 0px 0px 2em; vertical-align: middle;">
<h1 class="c-info__title " style="border: 0px; color: #333333; font-family: inherit; font-size: 1.38em; font-style: inherit; font-variant: inherit; line-height: 1.2; margin: 0px; overflow: hidden; padding: 0px; vertical-align: baseline;">
<a href="https://en.wikipedia.org/wiki/iA_Writer" style="border: 0px; font-family: inherit; font-size: 20px; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration: none; vertical-align: baseline;" title="iA Writer">iA Writer</a></h1>
<div class="c-info__content chomp js-ellipsis" style="border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0.75em 0px 0px; max-height: none !important; overflow: hidden; padding: 0px; vertical-align: baseline;">
iA Writer is a minimalist text editor for OS X and iOS developed by Information Architects Incorporated. The idea of iA Writer is "to keep you focused on just writing". iA Writer has been "downloaded 600,000 times by everyone from hobbyist writers to the bestselling author Augusten Burroughs." It is the top selling text editor in the App Store behind Apple's own Pages application.</div>
<div class="c-info__links" style="border: 0px; clear: both; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0.75em 0px 0px; max-width: 100%; overflow: hidden; padding: 0px; text-overflow: ellipsis; vertical-align: baseline; white-space: nowrap;">
<span class="chomp--link__icn" style="-webkit-font-smoothing: antialiased; border: 0px; display: inline-block; font-family: ddg-serp-icons !important; height: 16px; line-height: 13px; margin: 0px 0.5em 0px 0px; padding: 0px; position: relative; speak: none; text-align: center; vertical-align: middle; width: 16px;"></span><a class="c-info__link" href="https://en.wikipedia.org/wiki/iA_Writer" style="border: 0px; color: #888888; font-family: inherit; font-size: 0.9167em; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration: none; vertical-align: baseline;"><img class="zci__more-at__icon" height="16" src="https://duckduckgo.com/assets/icons/favicons/wikipedia.png" style="border: none; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: -3px 0px 0px; max-width: 16px; padding: 0px 0.5em 0px 0px; vertical-align: middle;" width="16" />More at Wikipedia </a><a class="c-info__link c-info__link--url" href="http://www.iawriter.com/" style="border: 0px; color: #888888; font-family: inherit; font-size: 0.9167em; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration: none; vertical-align: baseline;"><span class="sep c-info__links__sep" style="border-left-color: rgb(208, 208, 208); border-left-style: solid; border-width: 0px 0px 0px 1px; display: inline-block; float: none; font-family: inherit; font-style: inherit; font-variant: inherit; height: 1em; line-height: inherit; margin: 0px 0.75em; padding: 0px; position: relative; top: 0.15em; vertical-align: baseline; width: 0px;"></span>iawriter.com</a></div>
</div>
<br />
So last night, returning back from <a href="http://tek.phparch.com/" rel="nofollow" target="_blank">php[tek] 2015</a>, I was noting down a small list of upcoming conferences this fall in Markdown. But my memory was a bit fuzzy from the travel I decided to paste it into a <a href="http://in2.se/1IZ41gy" rel="nofollow" target="_blank">Gist on GitHub</a> so I could ask people in my network to inform me about missing events.<br />
<br />
And wow, it was a rush! <a href="http://twitter.com/" rel="nofollow" target="_blank">Twitter</a>, <a href="http://facebook.com/" target="_blank">Facebook</a> and other channels informed me about missing or wrong dates of conferences. People even forked <a href="http://in2.se/1IZ41gy" rel="nofollow" target="_blank">my gist</a> to help me updating the list!<br />
<br />
And this is why I love being part of the <a href="http://phpcommunity.org/" rel="nofollow" target="_blank">PHP Community</a>. You do a small thing and before you know it, people are there to help out to improve things. And when you read a tweet like the one below, you can't help it feeling good that such a little contribution could mean a lot to others.<br />
<br />
<blockquote class="twitter-tweet" lang="en">
<div dir="ltr" lang="en">
<a href="https://twitter.com/DragonBe">@DragonBe</a> is a <a href="https://twitter.com/hashtag/hero?src=hash">#hero</a> of the day. He created a gist with <a href="https://twitter.com/hashtag/php?src=hash">#php</a> conferences - <a href="https://t.co/zMbS9Py88x">https://t.co/zMbS9Py88x</a> . Awesome!</div>
— Piotr Pasich (@piotrpasich) <a href="https://twitter.com/piotrpasich/status/603285952275062784">May 26, 2015</a></blockquote>
<script async="" charset="utf-8" src="//platform.twitter.com/widgets.js"></script>
Thanks for helping everyone, especially those who forked my gist to update it.<br />
<br />
<blockquote class="twitter-tweet" lang="en">
<div dir="ltr" lang="en">
Many thanks to <a href="https://twitter.com/freyr">@freyr</a>, <a href="https://twitter.com/martinstoll">@MartinStoll</a>, <a href="https://twitter.com/abdala">@abdala</a> and <a href="https://twitter.com/Woecifaun">@woecifaun</a> for your contributions to the <a href="https://twitter.com/hashtag/php?src=hash">#php</a> <a href="https://twitter.com/hashtag/conference?src=hash">#conference</a> gist <a href="http://t.co/8pJVcnObGq">http://t.co/8pJVcnObGq</a></div>
— Michelangelo van Dam (@DragonBe) <a href="https://twitter.com/DragonBe/status/603313795038060544">May 26, 2015</a></blockquote>
<script async="" charset="utf-8" src="//platform.twitter.com/widgets.js"></script>
<a href="http://www.pinterest.com/pin/create/extension/?url=https%3A%2F%2Fdraft.blogger.com%2Fblogger.g%3FblogID%3D28215292%23editor%2Fsrc%3Dsidebar&media=https%3A%2F%2Ffarm6.staticflickr.com%2F5165%2F5350787982_fa7ee73975_o.jpg&xm=h&xv=sa1.35&description=" style="background-color: transparent; background-image: url(data:image/png; border: none; cursor: pointer; display: none; height: 20px; left: 153px; opacity: 0.85; position: absolute; top: 24px; width: 40px; z-index: 8675309;"></a><a href="http://www.pinterest.com/pin/create/extension/?url=https%3A%2F%2Fdraft.blogger.com%2Fblogger.g%3FblogID%3D28215292%23editor%2Fsrc%3Dsidebar&media=https%3A%2F%2Ffarm6.staticflickr.com%2F5165%2F5350787982_fa7ee73975_o.jpg&xm=h&xv=sa1.35&description=" style="background-color: transparent; background-image: url(data:image/png; border: none; cursor: pointer; display: none; height: 20px; left: 153px; opacity: 0.85; position: absolute; top: 24px; width: 40px; z-index: 8675309;"></a>M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com0tag:blogger.com,1999:blog-28215292.post-52153892793327293502015-05-05T13:30:00.000+02:002015-05-05T15:53:44.406+02:00popen for cli commands and pipes in php<div class="separator" style="clear: both; text-align: center;">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://www.flickr.com/photos/jonahgs/152740415/" imageanchor="1" rel="nofollow" style="margin-left: auto; margin-right: auto;" target="_blank"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuPDaeFQfy0GmrWH_r6uutm6SY16R9Xu2CCad2sptA0UzTLeoPEIep_DGT8nswmSfKrQqTek0OAkBFqzZTkVnZ14VusHLQzlGRdSPDNapGAEy0WUZqc-6xLdq6vt039cBa0KmUjg/s1600/command-line-piping-in-php.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Source: Pipes 1/3 by Jonah G.S. on Flickr.com</td></tr>
</tbody></table>
I got a question today about using commands that pipe output to other commands within PHP applications.<br />
<br />
There are two functions in PHP that are perfect for the task: <a href="http://php.net/popen" rel="nofollow" target="_blank">popen</a> and <a href="http://php.net/proc_open" rel="nofollow" target="_blank">proc_open</a>.<br />
<br />
The function "popen" opens a process file pointer, basically you have a pointer during the execution of a process. This functionality is often useful when you have one-way traffic (like piping commands on command line).<br />
<br />
The function "proc_open" behaves the same as popen, but gives you access to the input and the output, which makes it very useful for reading and writing as you go along.<br />
<br />
So let's say you have logic that generates a crontab entry, you can always do this using the commandline.<br />
<br />
<pre style="-webkit-print-color-adjust: exact; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; background-color: white; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;">/usr/bin/php crontab.php | /usr/bin/crontab</code></pre>
But when you want to run it as a complete process, you can go about using <a href="http://php.net/exec" rel="nofollow" target="_blank">exec</a>, <a href="http://php.net/shell_exec" rel="nofollow" target="_blank">shell_exec</a>, <a href="http://php.net/passthru" rel="nofollow" target="_blank">passthru</a> or <a href="http://php.net/system" rel="nofollow" target="_blank">system</a> and fiddle with <a href="http://php.net/escapeshellcmd" rel="nofollow" target="_blank">escapeshellcmd</a>. But often this looks messy and not reusable.<br />
<br />
A better approach would be to use "popen". A small example would look something like this:<br />
<br />
<pre style="-webkit-print-color-adjust: exact; border: 1px solid rgb(217, 217, 217); color: #737373; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; font-size: 11px; line-height: 16px; margin-bottom: 18px; padding: 14px; white-space: pre-wrap; word-wrap: break-word;"><code style="-webkit-print-color-adjust: exact; background-color: white; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; font-family: Monaco, 'Andale Mono', 'Courier New', monospace; padding: 0px;"><?php
$output = '*/5 * * * * /bin/echo "Hello World!" 2>&1' . PHP_EOL;
$command = '/usr/bin/crontab';
var_dump(cmdPipe($output, $command));
/**
* Functionality to pipe output
*
* @param string $input The command that needs to be executed
* @param string $commandline The command the first command needs to be
* piped to
* @return string The output of the given command
* @throws \RuntimeException
*/
function cmdPipe($input, $commandline)
{
if (false === ($pipe = popen("echo \"$input\"|$commandline", 'r'))) {
throw new \RuntimeException('Cannot open pipe');
}
$output = '';
while (!feof($pipe)) {
$output .= fread($pipe, 1024);
}
pclose($pipe);
return $output;
}</code></pre>
<b>DISCLAIMER: This is not secure code and should not be used as-is in production environments!</b><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidXb-BSofZ8l2qj5lq4u5yUqGbAXbID20ow9BjUxpU4W1l0HlJ0ALsTCXkOp9pqAicgQkSeUjh5CSAehfrJrxORfy86-OAk5gFzGKuTpXyPb2eRZgqUVVHYFK27ZEhaZbrCrMjRQ/s1600/Screenshot+2015-05-05+09.45.44.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidXb-BSofZ8l2qj5lq4u5yUqGbAXbID20ow9BjUxpU4W1l0HlJ0ALsTCXkOp9pqAicgQkSeUjh5CSAehfrJrxORfy86-OAk5gFzGKuTpXyPb2eRZgqUVVHYFK27ZEhaZbrCrMjRQ/s1600/Screenshot+2015-05-05+09.45.44.png" /></a></div>
Build it as a feature element and you now have a piping functionality you can nest, embed but most of all: reuse.M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com2tag:blogger.com,1999:blog-28215292.post-64407607863163459582015-04-27T20:39:00.000+02:002015-04-29T12:29:27.312+02:00Back from LoneStarPHP 2015<div style="color: #2d2d2d; font-family: OpenSans, sans-serif; font-size: 16px; margin-bottom: 24px; margin-top: 0px; outline: transparent solid 0px;">
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOHfw1Ol7ZTiUT8uo9CmGf8_OeoGViRnYOPR0sqRuYJQDH67_JqtOduLqGlisNzRfEerB3JSFoU4E27wi88dvuXAm5HdiQuoUpaHTcMG3JvxT6D8yXKaRACYhSaSXKqmjQFJKmLQ/s1600/lonestar_header.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="LoneStarPHP 2015" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOHfw1Ol7ZTiUT8uo9CmGf8_OeoGViRnYOPR0sqRuYJQDH67_JqtOduLqGlisNzRfEerB3JSFoU4E27wi88dvuXAm5HdiQuoUpaHTcMG3JvxT6D8yXKaRACYhSaSXKqmjQFJKmLQ/s1600/lonestar_header.jpg" height="223" title="LoneStarPHP Conference 2015, Addison, TX" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Listening to Phil Sturgeon (courtesy of Ben Marks) at LoneStarPHP 2015</td></tr>
</tbody></table>
<div>
I returned earlier this week from <a href="http://lonestarphp.com/" rel="nofollow" target="_blank">LoneStarPHP 2015</a>, a community PHP conference <span style="outline: transparent solid 0px;">held in Addison, a suburb of Dallas, Texas.</span></div>
</div>
<div style="color: #2d2d2d; font-family: OpenSans, sans-serif; font-size: 16px; margin-bottom: 24px; outline: transparent solid 0px;">
<span style="-webkit-touch-callout: none; outline: transparent solid 0px;">This conference was a three-day event, with a full day reserved for tutorial sessions where experts from all over the world gave full training and hands-on workshops on subjects like PHP foundations, unit testing, systems administration, API's, security and performance. A great decision made by the conference organizers to run a full day for training. </span></div>
<div style="color: #2d2d2d; font-family: OpenSans, sans-serif; font-size: 16px; margin-bottom: 24px; outline: transparent solid 0px;">
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjT_DfueInePiC5EM3oMvtlaMmWOzmnCu96Vq-2sByqxLbu5hJa7boRW_7C8jbxcCXVcVfd1f2igaMFUB2sbowi-bHWzlTpOQb0QFyfivezchbsLV5O-0bcGGsI7ftE-KMCBxthGw/s1600/2015-04-16+18.41.18.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjT_DfueInePiC5EM3oMvtlaMmWOzmnCu96Vq-2sByqxLbu5hJa7boRW_7C8jbxcCXVcVfd1f2igaMFUB2sbowi-bHWzlTpOQb0QFyfivezchbsLV5O-0bcGGsI7ftE-KMCBxthGw/s1600/2015-04-16+18.41.18.jpg" height="300" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Standing in line for a true Texas BBQ at Hard Eight BBQ</td></tr>
</tbody></table>
<span style="-webkit-touch-callout: none; outline: transparent solid 0px;">LoneStarPHP has a reputation to offer a true Texas BBQ to all speakers, and this year it was again a big success. We ended up at the "Hard Eight BBQ", one of the best BBQ restaurants in the US. A quarter pound of very tasty brisket, some Jalapeño Chicken Poppers, Spicy Sausage and a few Spare Ribs were on my plate. Just the amount of meat I could handle without getting a meat overdose.</span></div>
<div style="color: #2d2d2d; font-family: OpenSans, sans-serif; font-size: 16px; margin-bottom: 24px; outline: transparent solid 0px;">
<span style="-webkit-touch-callout: none; outline: transparent solid 0px;">The second and third day were all about PHP. Speakers were giving 50 minute sessions starting at 9am all the way until 5pm. LoneStarPHP attendees were given the best of the best and the audience loved it.</span></div>
<div style="color: #2d2d2d; font-family: OpenSans, sans-serif; font-size: 16px; margin-bottom: 24px; outline: transparent solid 0px;">
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEju2qq7jb_3KaBVFQaw2aZk2raQjKdB4armTEB70JvH5a-gBdUxnXvpIOwPsuf2Nm_J1dtf6sAo-MJxYscxs2cork_U4tDX3XiGOdKtqNIM-rLpyFIN8V8jlVd8R1WLuQ4Tm9bw7g/s1600/2015-04-18+17.25.59.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEju2qq7jb_3KaBVFQaw2aZk2raQjKdB4armTEB70JvH5a-gBdUxnXvpIOwPsuf2Nm_J1dtf6sAo-MJxYscxs2cork_U4tDX3XiGOdKtqNIM-rLpyFIN8V8jlVd8R1WLuQ4Tm9bw7g/s1600/2015-04-18+17.25.59.jpg" height="300" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Jeff Carrouth goes over the SOA architecture</td></tr>
</tbody></table>
I learned interesting things about Dependency Injection, Composer , API's, SOA's, Security, Testing, Guzzle to consume HTTP, Speaking at Conferences, Teaching Kids to Code and What it takes to run a tech company.</div>
<div style="color: #2d2d2d; font-family: OpenSans, sans-serif; font-size: 16px; margin-bottom: 24px; outline: transparent solid 0px;">
Between sessions there was of course the "hallway track", discussions between attendees about all kind of subjects which many consider the most important part of any conference.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvBtwVz8C6KtL0RaJ7UBDlQUkIeXPU3TSI9FbXXHOZzZv23o8dzS-EVetAEolEh_xhapnHeOW0ImhwxgkstA3EjMSVyewsVupU4EtVJSQG2CDuI3begMVKkM3w6tMqvIcyhFVn8w/s1600/2015-04-18+00.38.37.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvBtwVz8C6KtL0RaJ7UBDlQUkIeXPU3TSI9FbXXHOZzZv23o8dzS-EVetAEolEh_xhapnHeOW0ImhwxgkstA3EjMSVyewsVupU4EtVJSQG2CDuI3begMVKkM3w6tMqvIcyhFVn8w/s1600/2015-04-18+00.38.37.jpg" height="300" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">PHPTownHall and LooselyCoupled doing a joint-podcast session</td></tr>
</tbody></table>
Of course, evening social activities brought everyone closer and kept the conversation going. When you hang out with a bunch of PHP folks, you end up with a couple of podcast recordings as well. So, <a href="http://phptownhall.com/" rel="nofollow" target="_blank">PHPTownHall</a> and <a href="http://www.looselycoupled.info/" rel="nofollow" target="_blank">LooselyCoupled</a> joined forces one night and the amazing Godfather of the PHP community, Mr. <a href="http://blog.calevans.com/" rel="nofollow" target="_blank">Cal Evans</a> could not resist the urge to record another session of <a href="https://voicesoftheelephpant.com/" rel="nofollow" target="_blank">Voices of the Elephpant</a>: it's the booze talking with a round-table discussion with conference organizers and community leaders. On both occasions it was a great blast, just go listen to the podcasts.<br />
<br />
If you like a good BBQ mixed with new, refreshing and highly educational talks, LoneStarPHP is a conference you must experience.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTX0oRhgibYrlWPR0sfU3aGNOLm5gX14b798DBc4dcVZSoZTN0IuCwCfrHfJnf8ppLLsPW1oO8BTRubBDBUMmMLqvFSDMfrzRtBbYXTEb3Eau0vC09NuLJhtamjEtw_xsS4ln3fg/s1600/2015-04-18+12.51.52-1.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTX0oRhgibYrlWPR0sfU3aGNOLm5gX14b798DBc4dcVZSoZTN0IuCwCfrHfJnf8ppLLsPW1oO8BTRubBDBUMmMLqvFSDMfrzRtBbYXTEb3Eau0vC09NuLJhtamjEtw_xsS4ln3fg/s1600/2015-04-18+12.51.52-1.jpg" height="400" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">See you all at LoneStarPHP 2016</td></tr>
</tbody></table>
<br /></div>
M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com0tag:blogger.com,1999:blog-28215292.post-35366938060672968242015-01-16T13:30:00.000+01:002015-01-16T13:30:01.935+01:00New Year's Cleanup for VAT validator client for VIES service by European Commission<div class="separator" style="clear: both; text-align: center;">
<a href="https://packagist.org/packages/dragonbe/vies" imageanchor="1" rel="nofollow" style="margin-left: 1em; margin-right: 1em;" target="_blank"><img border="0" height="222" src="https://upload.wikimedia.org/wikipedia/en/thumb/8/84/European_Commission.svg/640px-European_Commission.svg.png" width="320" /></a></div>
<div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25px; margin-bottom: 16px;">
<br /></div>
<div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25px; margin-bottom: 16px;">
It's a new year and that's always good to clean up things and improve code. This is exactly what I did to make it easier for you to use the VIES service.</div>
<div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25px; margin-bottom: 16px;">
VIES is the VAT Information Exchange System provided by the European Commission to allow its members to validate VAT registration numbers of companies registered within the European Union. Since an invoice with an invalid VAT number can result in penalties, this client library is convenient to use in any B2B application.</div>
<div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25px; margin-bottom: 16px;">
This tool allows you to simply embed the service within your PHP application using <a href="http://getcomposer.org/" target="_blank">Composer</a> as the client is available in <a href="https://packagist.org/packages/dragonbe/vies" rel="nofollow" target="_blank">Packagist</a>. We even included <a href="https://travis-ci.org/DragonBe/vies" rel="nofollow" target="_blank">tests</a>, improved <a href="https://insight.sensiolabs.com/projects/21b019ce-dd1d-4d16-8b74-880b9ee5e795" rel="nofollow" target="_blank">quality</a> and examples for you to play with. The source code is freely available on <a href="https://github.com/DragonBe/vies" rel="nofollow" target="_blank">GitHub</a> under <a href="http://opensource.org/licenses/MIT" rel="nofollow" target="_blank">MIT License</a>.</div>
<div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25px; margin-bottom: 16px;">
<strong style="box-sizing: border-box;">I wish you a very happy 2015!</strong></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://insight.sensiolabs.com/projects/21b019ce-dd1d-4d16-8b74-880b9ee5e795/" imageanchor="1" rel="nofollow" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;" target="_blank"><img border="0" src="https://insight.sensiolabs.com/projects/21b019ce-dd1d-4d16-8b74-880b9ee5e795/big.png" /></a></div>
<div style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25px; margin-bottom: 16px;">
</div>
<h2 style="border-bottom-color: rgb(238, 238, 238); border-bottom-style: solid; border-bottom-width: 1px; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 1.75em; line-height: 1.225; margin-bottom: 16px; margin-top: 1em; padding-bottom: 0.3em; position: relative;">
<br /></h2>
<h2 style="border-bottom-color: rgb(238, 238, 238); border-bottom-style: solid; border-bottom-width: 1px; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 1.75em; line-height: 1.225; margin-bottom: 16px; margin-top: 1em; padding-bottom: 0.3em; position: relative;">
Changelog</h2>
<ul class="task-list" style="box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25px; margin-bottom: 0px !important; margin-top: 0px; padding: 0px 0px 0px 2em;">
<li style="box-sizing: border-box;">we got rid of <a href="http://framework.zend.com/" style="box-sizing: border-box; color: #4183c4; text-decoration: none;">Zend Framework 1</a></li>
<li style="box-sizing: border-box;">implemented <a href="http://www.php-fig.org/psr/psr-4/" style="box-sizing: border-box; color: #4183c4; text-decoration: none;">PSR-4</a></li>
<li style="box-sizing: border-box;">followed advice from <a href="https://insight.sensiolabs.com/projects/21b019ce-dd1d-4d16-8b74-880b9ee5e795/analyses/15" style="box-sizing: border-box; color: #4183c4; text-decoration: none;">SenioLabsInsight</a> to improve code quality</li>
<li style="box-sizing: border-box;">removed support for PHP 5.3, following <a href="http://php.net/archive/2014.php#id2014-08-14-1" style="box-sizing: border-box; color: #4183c4; text-decoration: none;">EOL announcement</a></li>
</ul>
M. van Damhttp://www.blogger.com/profile/12610668749799675317noreply@blogger.com0