{"componentChunkName":"component---src-templates-author-jsx","path":"/blog/author/erika_heidi/","result":{"data":{"prismic":{"allFeaturedblogs":{"edges":[{"node":{"featured_blogs_enabled":true,"heading":[{"type":"paragraph","text":"Featured posts","spans":[]}],"featured_blog_1":{"__typename":"PRISMIC_Blog","_linkType":"Link.document","blog_header_image":{"dimensions":{"width":790,"height":395},"alt":null,"copyright":null,"url":"https://images.prismic.io/www-static/6d8d81b1-971a-4313-b033-b4e125cb14a0_MondoDB-blog-header-790x395.PNG?auto=compress,format"},"blog_headline":[{"type":"heading1","text":"Introducing DigitalOcean Managed MongoDB – a fully managed, database as a service for modern apps","spans":[]}],"blog_post_date":"2021-06-29","blog_post_content":[{"type":"paragraph","text":"MongoDB is one of the most popular databases, and it’s ideal for apps that evolve rapidly and need to handle huge volumes of data and traffic. It offers advantages like flexible document schemas, code-native data access, change-friendly design, and easy horizontal scale-out.","spans":[{"start":22,"end":44,"type":"hyperlink","data":{"link_type":"Web","url":"https://db-engines.com/en/ranking","target":"_blank"}}]},{"type":"paragraph","text":"However, building and maintaining MongoDB clusters from the ground up can be a huge undertaking. Developers often complain that they have to spend their valuable time and resources on database management. Well, we’ve been listening and have some great news: accessing and managing MongoDB on DigitalOcean just got a lot simpler!","spans":[]},{"type":"paragraph","text":"We are excited to announce that DigitalOcean Managed MongoDB is now in General Availability. Managed MongoDB is a fully managed, database as a service (DBaaS) offering from DigitalOcean, built in partnership with and certified by MongoDB Inc. It provides you all the technical capabilities that make MongoDB so beloved in the developer community. Together we have ensured that you will get access to all the latest releases of the MongoDB document database as they become available.","spans":[{"start":32,"end":91,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/products/managed-databases-mongodb/"}},{"start":230,"end":241,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.mongodb.com/","target":"_blank"}}]},{"type":"paragraph","text":"Managed MongoDB simplifies the MongoDB administration. Developers of all skill levels, even those who do not have prior experience in databases, can spin up MongoDB clusters in just a few minutes. We handle the provisioning, managing, scaling, updates, backups, and security of your MongoDB clusters, allowing you to offload the complex, time consuming –yet critical – database administration tasks to us. This empowers you to focus on what really matters: building awesome apps.","spans":[]},{"type":"embed","oembed":{"height":113,"width":200,"embed_url":"https://www.youtube.com/watch?v=NvHQSV7jnKA","type":"video","version":"1.0","title":"Create a MongoDB Database on DigitalOcean","author_name":"DigitalOcean","author_url":"https://www.youtube.com/c/Digitalocean","provider_name":"YouTube","provider_url":"https://www.youtube.com/","cache_age":null,"thumbnail_url":"https://i.ytimg.com/vi/NvHQSV7jnKA/hqdefault.jpg","thumbnail_width":480,"thumbnail_height":360,"html":"<iframe width=\"200\" height=\"113\" src=\"https://www.youtube.com/embed/NvHQSV7jnKA?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>"}},{"type":"heading2","text":"Benefits of Managed MongoDB","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"list-item","text":"Easy set up and maintenance: We create the database clusters for you. Simply choose the cluster configuration (e.g., memory, disk size, number of nodes, etc.), and the data center in which you want to host the database. Follow a few simple steps and your database cluster will be up and running in a matter of minutes. You can spin up clusters using the cloud control panel, CLI, or API.\n\n","spans":[{"start":0,"end":28,"type":"strong"}]},{"type":"list-item","text":"Automatic daily backups with point in time recovery: Data is one of the most important assets of an app, so it’s critical to backup your database. We take backups of your entire clusters automatically on a daily basis, for free. We also provide a point in time recovery for 7 days, that way if things go wrong due to human error, machine error, or some combination of both, you can easily restore the database as it was at any point in the previous 7 days. \n\n","spans":[{"start":0,"end":52,"type":"strong"}]},{"type":"list-item","text":"Automatic updates and access to latest MongoDB releases: You get access to MongoDB 4.4. This is the latest release of MongoDB and comes packed with numerous enhancements like hedged reads, rust, and swift drivers. Since we have developed Managed MongoDB in partnership with MongoDB Inc, you will always get access to new releases as they become available. With Managed MongoDB, the updates happen automatically. Just select a date and time for the updates and we take care of the rest. This makes it easy to stay up to date with MongoDB releases without disrupting your business.\n\n","spans":[{"start":0,"end":56,"type":"strong"},{"start":148,"end":169,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.mongodb.com/new","target":"_blank"}}]},{"type":"list-item","text":"High availability with automated failover: If your database goes down, it can take down the entire app, leading to bad customer experiences. With Managed MongoDB, you can easily minimize the downtime for your database and make it highly available with standby nodes. Standby nodes add redundancy, so if for example the primary node fails, the standby node is immediately promoted to primary and begins serving requests while we provision a replacement standby node in the background.\n\n","spans":[{"start":0,"end":42,"type":"strong"}]},{"type":"list-item","text":"Scale up easily to handle traffic spikes: As your app gains traction and the usage grows, it’s important to have a database that can keep up with the increased demand. With Managed MongoDB, you can easily scale up the size of database nodes when needed.\n\n","spans":[{"start":0,"end":41,"type":"strong"}]},{"type":"list-item","text":"Secure by default: Since data is critical, it also needs to be secure. We encrypt data at rest with LUKS and in transit with SSL. When you create a new cluster, it’s placed in a VPC network by default that provides a more secure connection between resources. You can also restrict access to your nodes to prevent brute-force password and denial-of-service attacks.","spans":[{"start":0,"end":18,"type":"strong"},{"start":178,"end":189,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/docs/networking/vpc/"}}]},{"type":"heading2","text":"The need for Managed Databases","spans":[]},{"type":"paragraph","text":"DigitalOcean’s mission is to simplify cloud computing so developers, startups, and SMBs can spend more time building software that changes the world. While databases are a critical component to any application, building, maintaining, and scaling them can be complex and time consuming. For developers that are building apps for their business, database administration is often not a core focus area. But it’s quite common to find developers that write the code and then also roll up their sleeves to maintain databases. Such users would rather offload the tedious database administration and focus their limited time and energy on building and enhancing their apps. ","spans":[]},{"type":"paragraph","text":"With this in mind, we introduced Managed Databases a couple of years ago and are excited to add Managed MongoDB to our portfolio. With this release, DigitalOcean Managed Databases now supports the following engines:","spans":[{"start":33,"end":50,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/products/managed-databases/"}}]},{"type":"image","url":"https://images.prismic.io/www-static/87745cc1-1c5f-4463-b104-104b7fc30dc7_managed-databases-logos.png?auto=compress,format","alt":null,"copyright":null,"dimensions":{"width":849,"height":104}},{"type":"paragraph","text":"Managed MongoDB launch comes on the heels of DigitalOcean App Platform, a modern, reimagined PaaS (Platform as a Service) that we released a few months ago. App Platform makes it very easy to build, deploy, and scale apps and static sites. You can deploy code by simply pointing to your GitHub and GitLab repos, and App Platform will do all the heavy lifting of managing infrastructure, app runtimes, and dependencies. App Platform, along with Managed Databases, helps fulfill DigitalOcean’s mission by empowering developers, startups, and SMBs to focus more on their apps, and less on the underlying infrastructure and databases.","spans":[{"start":45,"end":70,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/products/app-platform/"}}]},{"type":"heading2","text":"How Managed MongoDB works","spans":[]},{"type":"paragraph","text":"DigitalOcean provides you with various compute options to build your apps like:","spans":[]},{"type":"list-item","text":"Droplets: On-demand, Linux virtual machines suitable for production business applications and personal passion projects.","spans":[{"start":0,"end":8,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/products/droplets/"}}]},{"type":"list-item","text":"DigitalOcean Kubernetes: Managed Kubernetes with automatic scaling, upgrades, and a free control plane.","spans":[{"start":0,"end":23,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/products/kubernetes/"}}]},{"type":"list-item","text":"DigitalOcean App Platform: A fully managed Platform as a Service.","spans":[{"start":0,"end":25,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/products/app-platform/"}}]},{"type":"paragraph","text":"No matter which compute option you choose to build your apps, you can easily add Managed MongoDB to it. In addition to this, Managed MongoDB also integrates with the Node.js 1-Click App from DigitalOcean Marketplace making it a lot easier to build Node.js apps.","spans":[{"start":166,"end":215,"type":"hyperlink","data":{"link_type":"Web","url":"https://marketplace.digitalocean.com/apps/nodejs"}}]},{"type":"heading2","text":"Simple, predictable pricing","spans":[]},{"type":"paragraph","text":"Just like all DigitalOcean products, Managed MongoDB provides simple, predictable pricing that allows you to control costs and prevent any surprise bills. You can spin up a database cluster for just $15/month, or a highly available three-node replica set for $45/month. Click here for more information.","spans":[{"start":270,"end":301,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/pricing/#managed-databases"}}]},{"type":"heading2","text":"Regional availability","spans":[]},{"type":"paragraph","text":"Managed MongoDB is currently available in the following regions:","spans":[]},{"type":"list-item","text":"NYC3 (New York, USA)","spans":[]},{"type":"list-item","text":"FRA1 (Frankfurt, Germany)","spans":[]},{"type":"list-item","text":"AMS3 (Amsterdam, Netherlands)","spans":[]},{"type":"paragraph","text":"We will be making Managed Mongo available in other regions soon. Please check out the release notes for most up to date information on regional availability.","spans":[{"start":86,"end":99,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/docs/release-notes/"}}]},{"type":"heading2","text":"Join us at deploy, DigitalOcean’s virtual user conference","spans":[]},{"type":"paragraph","text":"Today we have deploy, DigitalOcean’s signature user conference, which focuses on celebrating, educating, and connecting awesome builders from all over the world.","spans":[{"start":14,"end":20,"type":"hyperlink","data":{"link_type":"Web","url":"https://deploy.digitalocean.com/home"}}]},{"type":"paragraph","text":"Check out the keynote session from DigitalOcean's CEO, Yancey Spruill, in which he talks about where we're headed as a company and shares some exciting product updates. His keynote will be followed by sessions from community members, engineers, customers, and other experts that are building technologies and businesses powered by the cloud. With live Q&A and an active Discord server, there’s ample opportunity to engage and learn something new. Click here to attend the deploy conference.","spans":[{"start":14,"end":69,"type":"hyperlink","data":{"link_type":"Web","url":"https://deploy.digitalocean.com/agenda/session/552806"}},{"start":347,"end":384,"type":"hyperlink","data":{"link_type":"Web","url":"http://do.co/deploy-discord"}},{"start":461,"end":489,"type":"hyperlink","data":{"link_type":"Web","url":"http://do.co/deploy"}}]},{"type":"paragraph","text":"We are also launching a hackathon for DigitalOcean Managed MongoDB. Learn how you can participate, submit an app and get a t-shirt.","spans":[{"start":24,"end":66,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/mongodb-hackathon"}}]},{"type":"paragraph","text":"We hope you will give Managed MongoDB a try. Here are some sample datasets and sample apps that you can use to kick the tires. Check out the docs and let us know what you think!","spans":[{"start":22,"end":43,"type":"hyperlink","data":{"link_type":"Web","url":"https://cloud.digitalocean.com/databases/new?engine=mongodb"}},{"start":59,"end":90,"type":"hyperlink","data":{"link_type":"Web","url":"https://github.com/do-community/mongodb-resources","target":"_blank"}},{"start":141,"end":145,"type":"hyperlink","data":{"link_type":"Web","url":"https://docs.digitalocean.com/products/databases/mongodb/"}}]},{"type":"paragraph","text":"If you’d like to have a conversation about using DigitalOcean and Managed MongoDB in your business, please feel free to contact our sales team.","spans":[{"start":120,"end":142,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/company/contact/sales/"}}]},{"type":"paragraph","text":"Happy coding!","spans":[]},{"type":"paragraph","text":"André Bearfield","spans":[]},{"type":"paragraph","text":"Director of Product Management","spans":[]}],"tags":[{"tag1":{"__typename":"PRISMIC_Tag","tag":"Product Updates","_linkType":"Link.document","_meta":{"uid":"product-updates"}}}],"author":{"__typename":"PRISMIC_Author","author_name":"André Bearfield","author_image":{"dimensions":{"width":553,"height":547},"alt":"André Bearfield","copyright":null,"url":"https://images.prismic.io/www-static/fdc7c85186f0a850b04083e1d4306bd1c19772e8_andre-bearfield.png?auto=compress,format"},"_meta":{"uid":"andre-bearfield"}},"_meta":{"uid":"introducing-digitalocean-managed-mongodb"}},"featured_blog_2":{"__typename":"PRISMIC_Blog","_linkType":"Link.document","blog_header_image":{"dimensions":{"width":790,"height":400},"alt":"Droplet Console","copyright":null,"url":"https://images.prismic.io/www-static/710499ae-78cc-4179-afc1-15793637b200_DODX3727-790x400-logo-2.jpg?auto=compress,format"},"blog_headline":[{"type":"heading1","text":"Securely connect to Droplets with SSH key pairs using a new Droplet Console","spans":[]}],"blog_post_date":"2021-08-10","blog_post_content":[{"type":"paragraph","text":"The famous author Ken Blanchard once said, “Feedback is the breakfast of champions.\" This is something we truly believe at DigitalOcean, and we always strive to enhance our products based on customer feedback.","spans":[]},{"type":"paragraph","text":"With this goal in mind, we are excited to introduce a new Droplet Console that will make it much easier to connect to your Droplets securely. The new Droplet Console provides one-click SSH access to your Droplets through a native-like SSH/Terminal experience. It also eliminates the need for a password or manual configuration of SSH keys. Starting today, we’re pleased to announce that the new Droplet Console is now available to all Droplet users.","spans":[]},{"type":"heading2","text":"Why you should be using Secure Shell (SSH) ","spans":[]},{"type":"paragraph","text":"Password-based security is notoriously insecure due to password fatigue and the overuse of passwords such as ‘123456’. Secure Shell or SSH is a network communication protocol that solves this by using passwordless solutions for encryption, enabling two computers to communicate and securely share data. At a high level, SSH works by creating cryptographic key pairs consisting of a public and private key, which are computer generated and stored separately to ensure their security. ","spans":[{"start":80,"end":117,"type":"hyperlink","data":{"link_type":"Web","url":"https://cybernews.com/best-password-managers/most-common-passwords/"}}]},{"type":"paragraph","text":"SSH has become the default encryption protocol for many industries, but it was difficult to use SSH keys with DigitalOcean’s current Recovery (VNC) console, which is why we developed our new Droplet Console. The new Droplet Console is backed by an agent that security supervises the key pair, while also providing one-click SSH access to our users. You can see the full list of features below.","spans":[]},{"type":"heading2","text":"The new Droplet Console: More time saving, less time wasting ","spans":[]},{"type":"paragraph","text":"The new Droplet Console is for everyone who is looking to build fast, secure apps and avoid hassles with SSH access & usability issues.","spans":[]},{"type":"paragraph","text":"In addition to easier SSH access, the new Droplet Console comes with:","spans":[]},{"type":"list-item","text":"Copy/paste text: Instead of typing lengthy key pairs and text manually, you can use copy/paste to save time. ","spans":[{"start":0,"end":17,"type":"strong"}]},{"type":"list-item","text":"Multi-color support: Multi-color support makes the console more useful and intuitive, and breaks the conventional standard appearance which is black text on a white background. ","spans":[{"start":0,"end":41,"type":"strong"}]},{"type":"list-item","text":"Multi-language support: DigitalOcean’s new Droplet Console supports multiple languages, meaning you can now type and view any content in any language that is supported by UTF-8","spans":[{"start":0,"end":24,"type":"strong"}]},{"type":"list-item","text":"OS/images supported: Linux distributions (Ubuntu(16.04 - 20.04), Fedora (32 & 33), Debian (9), CentOS (7.6 & 8.3), CentOS 8 Stream, Rocky Linux and Marketplace images.","spans":[{"start":0,"end":20,"type":"strong"},{"start":148,"end":159,"type":"hyperlink","data":{"link_type":"Web","url":"https://marketplace.digitalocean.com/"}}]},{"type":"paragraph","text":"The new Droplet Console is available by default on any new Droplets you spin up. You can also enable it manually on older Droplets. Click here to learn more!","spans":[{"start":132,"end":157,"type":"hyperlink","data":{"link_type":"Web","url":"https://docs.digitalocean.com/products/droplets/how-to/connect-with-console/"}}]},{"type":"paragraph","text":"Check out this short walkthrough video that shows the new Droplet Console in action: ","spans":[]},{"type":"embed","oembed":{"type":"video","embed_url":"https://www.youtube.com/watch?v=Qt7QihVuxiE","title":"Access Your Droplet Terminal Through the Web Console","provider_name":"YouTube","thumbnail_url":"https://i.ytimg.com/vi/Qt7QihVuxiE/hqdefault.jpg","provider_url":"https://www.youtube.com/","author_name":"DigitalOcean","author_url":"https://www.youtube.com/c/Digitalocean","height":113,"width":200,"version":"1.0","thumbnail_height":360,"thumbnail_width":480,"html":"<iframe width=\"200\" height=\"113\" src=\"https://www.youtube.com/embed/Qt7QihVuxiE?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>"}},{"type":"paragraph","text":"We hope you’re excited about the new Droplet Console. You’re welcome to spin some Droplets up right now, and try out the new Droplet Console – why wait?","spans":[{"start":72,"end":103,"type":"hyperlink","data":{"link_type":"Web","url":"https://cloud.digitalocean.com/droplets/new"}}]},{"type":"paragraph","text":"Happy coding!","spans":[]},{"type":"paragraph","text":"Harsh Banwait, Senior Product Manager","spans":[]}],"tags":[{"tag1":{"__typename":"PRISMIC_Tag","tag":"Product Updates","_linkType":"Link.document","_meta":{"uid":"product-updates"}}}],"author":{"__typename":"PRISMIC_Author","author_name":"Harsh Banwait","author_image":{"dimensions":{"width":600,"height":399},"alt":null,"copyright":null,"url":"https://images.prismic.io/www-static/e83ff690-b20c-4d88-a2b6-57e562558cd6_download.png?auto=compress,format"},"_meta":{"uid":"harsh-banwait"}},"_meta":{"uid":"new-droplet-console-ssh-support"}},"featured_blog_3":{"__typename":"PRISMIC_Blog","_linkType":"Link.document","blog_header_image":{"dimensions":{"width":790,"height":400},"alt":null,"copyright":null,"url":"https://images.prismic.io/www-static/588e28d3-d41e-480b-937b-8c3b19201f6e_DODX3568-790x400-Blog.jpg?auto=compress,format"},"blog_headline":[{"type":"heading1","text":"How to scale your SaaS product without breaking the bank","spans":[]}],"blog_post_date":"2021-06-22","blog_post_content":[{"type":"paragraph","text":"These days, if you are in the business of software, chances are you are delivering or plan to deliver your services using a Software-as-a-Service (SaaS) model. A combination of internet-based delivery, subscription-based pricing, and low-friction product experiences have made SaaS solutions valuable tools for their users, and an excellent vehicle for software builders looking to distribute their products.","spans":[]},{"type":"paragraph","text":"These factors have made SaaS solutions ubiquitous; SaaS is the largest segment in the public cloud market, and is used to provide functionality ranging from personal finance apps for consumers, to productivity software for businesses, and even tools and services for software developers themselves to compose their applications and simplify their workflows. It is also not uncommon to find micro-SaaS applications being built for specific industries such as retail, job functions such as accounting or marketing, or tasks such as event management. ","spans":[]},{"type":"paragraph","text":"The best thing about this SaaS wave has been that it has allowed a new generation of software builders to build and monetize applications and participate in the digital economy. Previously, you had to be a big company with lots of resources, name recognition and distribution networks to successfully sell software products. Now, irrespective of whether you are a single person working on a passion project, a small team of developers in a startup, or a small and medium-sized business (SMB), the SaaS model enables you to express your ideas in the form of software and deliver them to customers anywhere in the world.","spans":[]},{"type":"heading2","text":"The unique challenges of building SaaS solutions","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"Despite the opportunities that come with the widespread adoption of SaaS products, software builders still have to answer key questions in their journey to building successful SaaS products. Understanding what customers to target, features to prioritize, how to price your product, and how to acquire customers are all critical questions to figure out while you are also doing the important job of actually building and operating the product. ","spans":[]},{"type":"paragraph","text":"Writing the code, testing, deployment, monitoring the usage in production, and ensuring that your apps are able to handle the additional demand when customer base and usage grows are all essential and time-consuming tasks.","spans":[]},{"type":"paragraph","text":"Additionally, being able to test multiple ideas, pivot, and double down on the ideas that actually work is critical in early stages of SaaS development. Once growth comes, it is equally important to scale up without compromising on performance or reliability. Needless to say, all of this needs to be economically viable as well, since not everyone has the resources of large SaaS providers like Salesforce or Adobe.","spans":[]},{"type":"heading2","text":"Cloud Computing enables builders but also poses challenges","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"Fortunately, for the act of building and operating your apps, cloud computing can help take some load off your shoulders. Unless you have the scale and resources of Facebook, chances are you are not going to set up your own data centers to host the computing infrastructure that powers your SaaS company. Public cloud infrastructure providers can bring great value to SaaS builders by providing on-demand computing services with usage-based pricing. However, just like how the legacy software companies weren't built for the SaaS model, the early (and big) cloud computing services were not optimized for the unique needs of small SaaS building teams. ","spans":[]},{"type":"paragraph","text":"Smaller SaaS teams face challenges with large cloud computing providers, including:","spans":[]},{"type":"heading4","text":"Too many technology options","spans":[]},{"type":"paragraph","text":"There are just too many options for tech stacks on which to build your SaaS - programming languages, application development frameworks, libraries, runtime environments, architectural patterns, and deployment models - and the list is growing by the day.","spans":[]},{"type":"heading4","text":"Complexity of cloud computing services","spans":[]},{"type":"paragraph","text":"Even when you have decided on a technology stack, there is a lot of cloud vendor-specific terminology you need to learn and heavy lifting you need to do to build on the cloud, not all of which contributes to making your SaaS applications successful.","spans":[]},{"type":"heading4","text":"Unpredictable costs","spans":[]},{"type":"paragraph","text":"The experimentation necessary in early stages of SaaS development, as well as the scaling of applications required during the growth phase, call for affordable and predictable pricing from your cloud provider. The last thing SaaS teams want is surprising and indecipherable bills from your cloud provider. Unfortunately, smaller businesses often experience unpredictable costs with cloud providers who are busy serving only the large enterprises.","spans":[]},{"type":"heading2","text":"DigitalOcean provides a simple, cost effective solution for SaaS builders","spans":[]},{"type":"paragraph","text":"Fortunately, at DigitalOcean we have a laser focus on small software development teams, who are trying to build the next generation of applications. Today, DigitalOcean customers are already building SaaS applications which serve all kinds of customers.","spans":[{"start":191,"end":217,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/solutions/saas/"}}]},{"type":"paragraph","text":"We believe SaaS builders should focus on building apps that power their business, and not spend their valuable time on managing infrastructure. That is exactly what we have been able to enable through our intuitive products that are built for scale and reliability.","spans":[{"start":205,"end":223,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/products/"}}]},{"type":"list-item","text":"Vidazoo is an advertising technology company specializing in video streaming and serving. It serves video ads to thousands of websites and handles close to 10 billion requests per day. \n\n“We are as much a data company as an adtech company. Our business relies on speedy and accurate data processing at massive scale. DigitalOcean provides us the perfect set of tools to operate our SaaS business profitably, while not making us feel the need to become full time system administrators. We plan to move a lot of our apps to DigitalOcean App Platform and other fully managed products.” - Roman Svichar, CTO of Vidazoo","spans":[{"start":0,"end":7,"type":"hyperlink","data":{"link_type":"Web","url":"https://vidazoo.com/"}},{"start":187,"end":583,"type":"em"}]},{"type":"paragraph","text":"We believe in meeting customers where they are. If they already have an understanding of cloud infrastructure technologies, they should be able to leverage that knowledge and get started with our products without any further ramp up.","spans":[]},{"type":"list-item","text":"Whatfix is an enterprise SaaS provider that offers a digital adoption platform to businesses. The company helps enterprises gain the full value of their investments in enterprise applications by providing real-time, interactive, and contextual guidance to users of those applications. \n\n“What we really love about the DigitalOcean platform is the ease of use. We feel like we know infrastructure and can handle most of the configuration and management. What we needed from a cloud was not bells and whistles but efficiency and reliability. DigitalOcean provides us a platform to build our apps and then gets out of the way. Just how we like it.” - Achyuth Krishna, Director of Engineering of Whatfix","spans":[{"start":0,"end":7,"type":"hyperlink","data":{"link_type":"Web","url":"https://whatfix.com/blog/driving-the-future-now-were-excited-to-announce-our-90-million-series-d-funding/"}},{"start":287,"end":648,"type":"em"}]},{"type":"paragraph","text":"We understand that scaling while maintaining reliability of applications and profitability of business is important, so we provide robust solutions which minimize downtime.","spans":[]},{"type":"list-item","text":"Centra is a SaaS-based e-commerce platform for global direct-to-consumer and wholesale e-commerce brands. Centra provides a powerful e-commerce backend that lets brands build pixel-perfect, custom designed, online flagship stores. \n\n“How do we enable our customers to create differentiated online experiences? How do we ensure their e-commerce apps stay up and running at all times? How do we scale on-demand when traffic grows or new customers come in? These are the questions that we ask ourselves every day. Thankfully, we have a partner in DigitalOcean that provides just the platform to answer those questions enabling us to guarantee 99.9% uptime for our clients.” - Martin Jensen, CEO of Centra","spans":[{"start":0,"end":6,"type":"hyperlink","data":{"link_type":"Web","url":"https://centra.com/"}},{"start":233,"end":673,"type":"em"}]},{"type":"paragraph","text":"These are just a few examples of SaaS businesses finding success on DigitalOcean. We are constantly amazed by the creativity and innovation that software builders are utilizing our platform for. If you are interested in learning more about product updates, technical deep-dives and best practices for building SaaS products and businesses, please contact us to learn how we can help you get started. ","spans":[{"start":340,"end":357,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/migrate/?utmmedium=blog","target":"_blank"}}]},{"type":"paragraph","text":"Come build with DigitalOcean!","spans":[]},{"type":"paragraph","text":"Looking to migrate your SaaS to DigitalOcean? Leverage free infrastructure credits, robust training, and technical support to ensure a worry-free migration.","spans":[{"start":0,"end":156,"type":"strong"},{"start":0,"end":156,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/migrate/?utmmedium=blog","target":"_blank"}}]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"Raman Sharma","spans":[]},{"type":"paragraph","text":"Vice President, Product & Programs Marketing","spans":[]}],"tags":[{"tag1":{"__typename":"PRISMIC_Tag","tag":"Developer Relations","_linkType":"Link.document","_meta":{"uid":"developer-relations"}}}],"author":{"__typename":"PRISMIC_Author","author_name":"Raman Sharma","author_image":{"dimensions":{"width":512,"height":512},"alt":null,"copyright":null,"url":"https://images.prismic.io/www-static/497b4b14-d192-493a-8b66-7ae176ba99f3_raman.png?auto=compress,format"},"_meta":{"uid":"raman-sharma"}},"_meta":{"uid":"how-to-scale-your-saas-product-without-breaking-the-bank"}}}}]}}},"pageContext":{"limit":12,"skip":0,"numAuthorPages":1,"currentPage":1,"uid":"erika_heidi","data":[{"node":{"author":{"_linkType":"Link.document","author_name":"Erika Heidi","author_image":null,"_meta":{"uid":"erika_heidi"}},"blog_header_image":{"dimensions":{"width":784,"height":418},"alt":"elephant super heros in masks flying with the words 'Get ready for PHP 7'","copyright":null,"url":"https://images.prismic.io/www-static/eda8fb19-1f01-4d9e-b729-59107e7fecf0_get_ready.jpg?auto=compress,format"},"blog_headline":[{"type":"heading1","text":"Getting Ready for PHP 7","spans":[]}],"blog_post_content":[{"type":"paragraph","text":"2015 has been an important year for PHP. Eleven years after its 5.0 release, a new major version is finally coming our way! PHP 7 is scheduled for release before the end of the year, bringing many new language features and an impressive performance boost.","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"But how will this impact your current PHP codebase? What really changed? How safe is it to update? This post will answer these questions and give you a taste of what's to come with PHP 7.","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"heading2","text":"Performance Improvements","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"Performance is undoubtedly the biggest reason why you should upgrade your servers as soon as a stable version is released. The core refactoring introduced by the [phpng RFC](https://wiki.php.net/rfc/phpng) makes PHP 7 as fast as (or faster than) HHVM. The official benchmarks are impressive: most real world applications running on PHP 5.6 will run at least twice as fast on PHP 7. ","spans":[{"start":358,"end":371,"type":"strong"}]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"For detailed performance benchmarks, have a look at Rasmus Lerdorf's presentation at PHP Australia. (You can use the arrow keys to navigate through the slides.) Here are some WordPress benchmarks from that presentation:","spans":[{"start":52,"end":98,"type":"hyperlink","data":{"link_type":"Web","url":"http://talks.php.net/oz15#/wpbench"}}]},{"type":"paragraph","text":"","spans":[]},{"type":"image","url":"https://images.prismic.io/www-static/fa4737dd-0d2a-4389-8809-fccf2128af79_php7_graph.jpg?auto=compress,format","alt":null,"copyright":null,"dimensions":{"width":784,"height":490}},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"PHP 7 handles more than twice as many requests per second, which in practical terms will represent a 100% improvement on performance for Wordpress websites.","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"heading2","text":"Backwards Compatibility Pitfalls","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"Let's talk about the few things that could potentially break a legacy application running on older versions of PHP.","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"heading3","text":" Deprecated Items Removed","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"A number of deprecated items have been removed. Because they've been deprecated for some time now, hopefully you aren't using them! This might, however, have an impact on legacy applications.","spans":[{"start":12,"end":46,"type":"hyperlink","data":{"link_type":"Web","url":"https://wiki.php.net/rfc/remove_deprecated_functionality_in_php7"}}]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"In particular, ASP-style tags ( `<%`, `<%=` and `%>` ), were removed along with script tags ( `<script language=\"php\">` ). Make sure you are using the recommended `<?php` tag instead. Other functions that were previously deprecated, like [split](http://php.net/manual/en/function.split.php), have also been removed in PHP 7.","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"The ereg extension (and all `ereg_*` functions) have been deprecated since PHP 5.3. It should be replaced with the PCRE extension (`preg_*` functions), which offers many more features. The mysql extension (and the `mysql_*` functions) have been deprecated since PHP 5.5.  For a direct migration, you can use the mysqli extension and the `mysqli_*` functions instead.","spans":[{"start":4,"end":8,"type":"strong"},{"start":115,"end":119,"type":"strong"},{"start":189,"end":194,"type":"strong"},{"start":245,"end":269,"type":"hyperlink","data":{"link_type":"Web","url":"https://wiki.php.net/rfc/mysql_deprecation"}},{"start":312,"end":318,"type":"strong"}]},{"type":"paragraph","text":"","spans":[]},{"type":"heading3","text":" Uniform Variable Syntax","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"The [uniform variable syntax](https://wiki.php.net/rfc/uniform_variable_syntax) is meant to solve a series of inconsistencies when evaluating variable-variable expressions. Consider the following code:","spans":[]},{"type":"paragraph","text":"```[php]{`","spans":[]},{"type":"paragraph","text":"    <?php  ","spans":[]},{"type":"paragraph","text":"    class Person  ","spans":[]},{"type":"paragraph","text":"    {","spans":[]},{"type":"paragraph","text":"       public $name = 'Erika';","spans":[]},{"type":"paragraph","text":"       public $job = 'Developer Advocate';","spans":[]},{"type":"paragraph","text":"    }","spans":[]},{"type":"paragraph","text":"    ","spans":[]},{"type":"paragraph","text":"    $person = new Person();","spans":[]},{"type":"paragraph","text":"    $property = [ 'first' => 'name', 'second' => 'info' ];","spans":[]},{"type":"paragraph","text":"    echo \"\\nMy name is \" . $person->$property['first'] . \"\\n\\n\";  ","spans":[]},{"type":"paragraph","text":"`}```    ","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"In PHP 5, the expression `$person->$property['first']` is evaluated as `$person->{$property['first']}`. In practical terms, this will be interpreted as `$person->name`, giving you the result \"My name is Erika\". Even though this is an edge case, it shows clear inconsistencies with the normal expression evaluation order, which is left to right.","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"In PHP 7, the expression `$person->$property['first']` is evaluated as `{$person->$property}['first']`. The interpreter will evaluate `$person->$property` first; consequently, the previous code example won't work in PHP 7 because `$property` is an array and cannot be converted to a string.","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"A quick and easy way to fix this problem is by explicitly defining the evaluation order with the help of curly braces (e.g. `$person->{$property['first']}`), which will guarantee the same behavior on both PHP 5 and PHP 7.","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"Thanks to the new uniform left-to-right variable syntax, many expressions previously treated as invalid will now become valid. To illustrate this new behavior, consider the following class:","spans":[]},{"type":"paragraph","text":"```[php]{`","spans":[]},{"type":"paragraph","text":"    <?php  ","spans":[]},{"type":"paragraph","text":"    class Person  ","spans":[]},{"type":"paragraph","text":"    {","spans":[]},{"type":"paragraph","text":"       public static $company = 'DigitalOcean';","spans":[]},{"type":"paragraph","text":"       public function getFriends()","spans":[]},{"type":"paragraph","text":"       {","spans":[]},{"type":"paragraph","text":"           return [","spans":[]},{"type":"paragraph","text":"               'erika' => function () {","spans":[]},{"type":"paragraph","text":"                   return 'Elephpants and Cats';","spans":[]},{"type":"paragraph","text":"               },","spans":[]},{"type":"paragraph","text":"               'sammy' => function () {","spans":[]},{"type":"paragraph","text":"                   return 'Sharks and Penguins';","spans":[]},{"type":"paragraph","text":"               }","spans":[]},{"type":"paragraph","text":"           ];","spans":[]},{"type":"paragraph","text":"       }","spans":[]},{"type":"paragraph","text":"    ","spans":[]},{"type":"paragraph","text":"       public function getFriendsOf($someone)","spans":[]},{"type":"paragraph","text":"       {","spans":[]},{"type":"paragraph","text":"           return $this->getFriends()[$someone];","spans":[]},{"type":"paragraph","text":"       }","spans":[]},{"type":"paragraph","text":"    ","spans":[]},{"type":"paragraph","text":"       public static function getNewPerson()","spans":[]},{"type":"paragraph","text":"       {","spans":[]},{"type":"paragraph","text":"           return new Person();","spans":[]},{"type":"paragraph","text":"       }","spans":[]},{"type":"paragraph","text":"    }","spans":[]},{"type":"paragraph","text":"`}```    ","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"With PHP 7, we can create nested associations and different combinations between operators:","spans":[]},{"type":"paragraph","text":"```[php]{`","spans":[]},{"type":"paragraph","text":"    $person = new Person();","spans":[]},{"type":"paragraph","text":"    echo \"\\n\" . $person->getFriends()['erika']() . \"\\n\\n\";  ","spans":[]},{"type":"paragraph","text":"    echo \"\\n\" . $person->getFriendsOf('sammy')() . \"\\n\\n\";  ","spans":[]},{"type":"paragraph","text":"`}```    ","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"This snippet would give us a parse error on PHP 5, but works as expected on PHP 7.","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"Similarly, nested static access is also possible:","spans":[]},{"type":"paragraph","text":"```[php]{`","spans":[]},{"type":"paragraph","text":"    echo \"\\n\" . $person::getNewPerson()::$company . \"\\n\\n\";  ","spans":[]},{"type":"paragraph","text":"    `}```","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"In PHP 5, this would give us the classic `T_PAAMAYIM_NEKUDOTAYIM` syntax error.","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"heading3","text":"Fatal Error with multiple \"default\" clauses","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"This is, again, an edge case and it's more related to logic errors in your code. There's no use for multiple default clauses in a switch, but because it never caused any trouble (e.g. no warnings), it can be difficult to detect the mistake. In PHP 5, the last *default* would be used, but in PHP 7 you will now get a *Fatal Error: Switch statements may only contain one default clause*.","spans":[{"start":100,"end":136,"type":"hyperlink","data":{"link_type":"Web","url":"https://wiki.php.net/rfc/switch.default.multiple"}},{"start":261,"end":268,"type":"em"},{"start":318,"end":384,"type":"em"}]},{"type":"paragraph","text":"","spans":[]},{"type":"heading3","text":"Engine Exceptions","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"Engine exceptions are meant to facilitate handling errors in your application. Existing fatal and recoverable fatal errors were replaced by exceptions, making it possible for us to catch said errors and take action — like displaying them in a nicer way, logging them, or performing recovery procedures.","spans":[{"start":0,"end":17,"type":"hyperlink","data":{"link_type":"Web","url":"https://wiki.php.net/rfc/engine_exceptions_for_php7"}}]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"The implementation of engine exceptions was done in such a way to keep backwards compatibility, but there is an edge case that could impact legacy applications when they have a custom error handling function in place. Consider the following code:","spans":[]},{"type":"paragraph","text":"```[php]{`","spans":[]},{"type":"paragraph","text":"    <?php  ","spans":[]},{"type":"paragraph","text":"    set_error_handler(function ($code, $message) {  ","spans":[]},{"type":"paragraph","text":"       echo \"ERROR $code: \" . $message . \"\\n\\n\";","spans":[]},{"type":"paragraph","text":"    });","spans":[]},{"type":"paragraph","text":"    ","spans":[]},{"type":"paragraph","text":"    function a(ArrayObject $b){  ","spans":[]},{"type":"paragraph","text":"       return $b;","spans":[]},{"type":"paragraph","text":"    }","spans":[]},{"type":"paragraph","text":"    ","spans":[]},{"type":"paragraph","text":"    a(\"test\");","spans":[]},{"type":"paragraph","text":"    ","spans":[]},{"type":"paragraph","text":"    echo \"Hello World\";  ","spans":[]},{"type":"paragraph","text":"    `}```","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"This code generates a recoverable error caused by the type mismatch when calling the function `a()` using a string as parameter. In PHP 5, it generates an `E_RECOVERABLE` that is caught by the custom error handler, so this is the output you get:","spans":[]},{"type":"paragraph","text":"```[php]{`","spans":[]},{"type":"paragraph","text":"    ERROR 4096: Argument 1 passed to a() must be an instance of ArrayObject, string given, called in /data/Projects/php7dev/tests/test04.php on line 12 and defined(...)","spans":[]},{"type":"paragraph","text":"    ","spans":[]},{"type":"paragraph","text":"    Hello World  ","spans":[]},{"type":"paragraph","text":"    `}```","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"Notice that the execution continues because the error was handled. In PHP 7, this code generates a `TypeError` exception (not an error!) so the custom error handler won't be called. This is the output you get:","spans":[]},{"type":"paragraph","text":"```[php]{`","spans":[]},{"type":"paragraph","text":"    Fatal error: Uncaught TypeError: Argument 1 passed to a() must be an instance of ArrayObject, string given, called in /vagrant/tests/test04.php on line 12 and defined in /vagrant/tests/test04.php:7  ","spans":[]},{"type":"paragraph","text":"    Stack trace:  ","spans":[]},{"type":"paragraph","text":"    #0 /vagrant/tests/test04.php(12): a('test')","spans":[]},{"type":"paragraph","text":"    #1 {main}","spans":[]},{"type":"paragraph","text":"      thrown in /vagrant/tests/test04.php on line 7","spans":[]},{"type":"paragraph","text":"    `}```","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"The execution is stopped because the exception was not caught. To solve this problem, you should catch the exceptions using try/catch blocks. It's important to notice that the [Exception hierarchy](https://wiki.php.net/rfc/throwable-interface) had to change to accommodate the new engine exceptions with minimal impact on legacy code:","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"list-item","text":"Throwable interface","spans":[]},{"type":"list-item","text":"Exception implements Throwable","spans":[]},{"type":"list-item","text":"ErrorException extends Exception","spans":[]},{"type":"list-item","text":"RuntimeException extends Exception","spans":[]},{"type":"list-item","text":"Error implements Throwable","spans":[]},{"type":"list-item","text":"TypeError extends Error","spans":[]},{"type":"list-item","text":"ParseError extends Error","spans":[]},{"type":"list-item","text":"AssertionError extends Error","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"This basically means that the new catch-all Exception is now `Throwable` instead of `Exception`. This should not impact any legacy code, but keep it in mind when handling the new engine exceptions in PHP 7.","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"heading2","text":"New Language Features","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"Now the fun part — let's talk about the most exciting new features that will be available when you upgrade to PHP 7.","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"heading3","text":"New Operators","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"PHP 7 comes with two shiny new operators: the spaceship (or combined comparison operator) and the null coalesce operator.","spans":[{"start":46,"end":55,"type":"strong"},{"start":98,"end":120,"type":"strong"}]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"The spaceship operator ( `<=>` ), also known as combined comparison operator, can be used to make your chained comparison more concise. Consider the following expression:","spans":[{"start":4,"end":22,"type":"hyperlink","data":{"link_type":"Web","url":"https://wiki.php.net/rfc/combined-comparison-operator"}}]},{"type":"paragraph","text":"```[php]{`","spans":[]},{"type":"paragraph","text":"    $a <=> $b","spans":[]},{"type":"paragraph","text":"`}```    ","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"This expression will evaluate to **-1** if `$a` is smaller than `$b`, **0** if `$a` equals `$b`, and **1** if `$a` is greater than `$b`. It's basically a shortcut for the following expression:","spans":[{"start":35,"end":37,"type":"strong"},{"start":72,"end":73,"type":"strong"},{"start":103,"end":104,"type":"strong"}]},{"type":"paragraph","text":"```[php]{`","spans":[]},{"type":"paragraph","text":"    ($a < $b) ? -1 : (($a > $b) ? 1 : 0)","spans":[]},{"type":"paragraph","text":"    `}```   ","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"The null coalesce operator ( `??` ) also works as a shortcut for a common use case: a conditional attribution that checks if a value is set before using it. In PHP 5, you would usually do something like this:","spans":[{"start":4,"end":26,"type":"hyperlink","data":{"link_type":"Web","url":"https://wiki.php.net/rfc/isset_ternary"}}]},{"type":"paragraph","text":"```[php]{`","spans":[]},{"type":"paragraph","text":"    $a = isset($b) ? $b : \"default\";","spans":[]},{"type":"paragraph","text":"`}```       ","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"With the null coalesce operator in PHP 7, we can simply use:","spans":[]},{"type":"paragraph","text":"```[php]{`","spans":[]},{"type":"paragraph","text":"    $a = $b ?? \"default\";","spans":[]},{"type":"paragraph","text":"    `}```   ","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"heading3","text":"Scalar Type Hints","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"One of the most debated new features coming with PHP 7, scalar type hints, will finally make it possible to use integers, floats, strings, and booleans as type hints for functions and methods. By default, scalar type hints are non-restrictive, which means that if you pass a float value to an integer parameter, it will just coerce it to int without generating any errors or warnings.","spans":[{"start":56,"end":73,"type":"hyperlink","data":{"link_type":"Web","url":"https://wiki.php.net/rfc/scalar_type_hints_v5","target":"_blank"}}]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"It is possible, however, to enable a strict mode that will throw errors when the wrong type is passed as an argument. Consider the following code:","spans":[]},{"type":"paragraph","text":"```[php]{`","spans":[]},{"type":"paragraph","text":"    <?php  ","spans":[]},{"type":"paragraph","text":"    function double(int $value)  ","spans":[]},{"type":"paragraph","text":"    {","spans":[]},{"type":"paragraph","text":"       return 2 * $value;","spans":[]},{"type":"paragraph","text":"    }","spans":[]},{"type":"paragraph","text":"    $a = double(\"5\");","spans":[]},{"type":"paragraph","text":"    var_dump($a);  ","spans":[]},{"type":"paragraph","text":"   `}```    ","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"This code won't generate any errors because we are not using strict mode. The only thing that will happen is a type conversion, so the string \"5\" passed as an argument will be coerced into integer inside the double function.","spans":[{"start":208,"end":214,"type":"em"}]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"If we want to make sure only integers are allowed to be passed to the double function, we can enable strict mode by including the directive `declare(strict_types = 1)` as the very first line in our script:","spans":[{"start":70,"end":76,"type":"em"}]},{"type":"paragraph","text":"```[php]{`","spans":[]},{"type":"paragraph","text":"    <?php  ","spans":[]},{"type":"paragraph","text":"    declare(strict_types = 1);  ","spans":[]},{"type":"paragraph","text":"    function double(int $value)  ","spans":[]},{"type":"paragraph","text":"    {","spans":[]},{"type":"paragraph","text":"       return 2 * $value;","spans":[]},{"type":"paragraph","text":"    }","spans":[]},{"type":"paragraph","text":"    $a = double(\"5\");","spans":[]},{"type":"paragraph","text":"    var_dump($a);  ","spans":[]},{"type":"paragraph","text":"   `}```    ","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"This code will generate a Fatal error: Uncaught TypeError: Argument 1 passed to double() must be of the type integer, string given.","spans":[{"start":26,"end":130,"type":"em"}]},{"type":"paragraph","text":"","spans":[]},{"type":"heading3","text":" Return Type Hints","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"Another important new feature coming with PHP 7 is the ability to define the return type of methods and functions, and it behaves in the same fashion as scalar type hints in regards of coercion and strict mode:","spans":[{"start":77,"end":88,"type":"hyperlink","data":{"link_type":"Web","url":"https://wiki.php.net/rfc/return_types"}}]},{"type":"paragraph","text":"```[php]{`","spans":[]},{"type":"paragraph","text":"    <?php  ","spans":[]},{"type":"paragraph","text":"    function a() : bool  ","spans":[]},{"type":"paragraph","text":"    {","spans":[]},{"type":"paragraph","text":"       return 1;","spans":[]},{"type":"paragraph","text":"    }","spans":[]},{"type":"paragraph","text":"    var_dump(a());  ","spans":[]},{"type":"paragraph","text":"`}```    ","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"This snippet will run without warnings and the returned value will be converted to bool automatically. If you enable strict mode (just the same as with scalar type hints), you will get a fatal error instead:","spans":[]},{"type":"paragraph","text":"```[php]{`","spans":[]},{"type":"paragraph","text":"`Fatal error: Uncaught TypeError: Return value of a() must be of the type boolean, integer returned`","spans":[]},{"type":"paragraph","text":"`}```","spans":[]},{"type":"paragraph","text":"Once again, notice that these errors are actually Exceptions that can be caught and handled using try/catch blocks. It's also important to highlight that you can use any valid type hint, not only scalar types.","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"heading2","text":"What's Next","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"The PHP 7 timeline indicates a stable release in mid-October, subject to quality. We are currently on release candidate cycles, and a beta version is already available for tests. Check out the RFC with all changes coming with PHP 7 for more information.","spans":[{"start":3,"end":18,"type":"hyperlink","data":{"link_type":"Web","url":"https://wiki.php.net/rfc/php7timeline"}},{"start":134,"end":146,"type":"hyperlink","data":{"link_type":"Web","url":"http://php.net"}},{"start":193,"end":231,"type":"hyperlink","data":{"link_type":"Web","url":"https://wiki.php.net/rfc#php_70"}}]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"Note that even though no new features will be included, some changes might still happen before the final release, so please don't use PHP 7 in production just yet! There's a Vagrant VM created and shared by Rasmus Lerdorf that you can use to test your current code on PHP 7. You are strongly encouraged to test your applications and report any problems you might find.","spans":[{"start":174,"end":184,"type":"hyperlink","data":{"link_type":"Web","url":"https://github.com/rlerdorf/php7dev"}}]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"Happy coding!","spans":[]},{"type":"paragraph","text":"","spans":[]},{"type":"paragraph","text":"by Erika Heidi","spans":[{"start":3,"end":14,"type":"hyperlink","data":{"link_type":"Web","url":"https://twitter.com/erikaheidi"}}]}],"blog_post_date":"2015-07-15","tags":[{"tag1":{"tag":"Engineering","_linkType":"Link.document","_meta":{"uid":"engineering"}}}],"_meta":{"uid":"getting-ready-for-php-7"}}},{"node":{"author":{"_linkType":"Link.document","author_name":"Erika Heidi","author_image":null,"_meta":{"uid":"erika_heidi"}},"blog_header_image":{"dimensions":{"width":784,"height":392},"alt":"Horizontally Scaling PHP Applications text on illustration of elephants walking linking trunks and tails","copyright":null,"url":"https://images.prismic.io/www-static/b8ae3d37c96d34df42840479b49ae13601411d0c_hero-2.jpg?auto=compress,format"},"blog_headline":[{"type":"heading1","text":"Horizontally Scaling PHP Applications","spans":[]}],"blog_post_content":[{"type":"paragraph","text":"Shipping a website or application to production has its own challenges, but when it gets the right traction, it's a great accomplishment. It always feels good to see the visitor numbers going up, doesn't it? Except, of course, when your traffic increases so much that it crashes your little LAMP stack. No matter what time or day it is, the cost of your app being offline is just too high, and in many cases it brings irreversible losses to a business.","spans":[]},{"type":"paragraph","text":"But fear not! There are ways to make your PHP application much more reliable and consistent. If the term scalability crossed your mind, you've got the right idea.","spans":[]},{"type":"paragraph","text":"In a nutshell, scalability is the ability of a system to handle an increased amount of traffic or processing and accommodate growth while maintaining a desirable user experience. There are basically two ways of scaling a system: vertically, also known as scaling up, and horizontally, also known as scaling out.","spans":[{"start":15,"end":26,"type":"em"},{"start":255,"end":265,"type":"em"},{"start":299,"end":310,"type":"em"}]},{"type":"paragraph","text":"Vertical scaling is accomplished by increasing system resources, like adding more memory and processing power. Resizing a Droplet, for instance, is vertical scaling. While this can work as an immediate solution, it might be hiding the real problems underneath your application, and there's no guarantee a server twice as powerful will run your app twice as fast.","spans":[]},{"type":"paragraph","text":"Horizontal scaling, on the other hand, is accomplished by adding more servers to an existing cluster. Let's talk about exactly what that means.","spans":[]},{"type":"heading2","text":"What is Horizontal Scaling?","spans":[]},{"type":"paragraph","text":"A cluster is simply a group of servers. A load balancer distributes the workload between the servers in a cluster. At any point, a new web server can be added to the existing cluster to handle more requests from users accessing your application; this is horizontal scaling.","spans":[{"start":2,"end":9,"type":"em"},{"start":42,"end":55,"type":"em"},{"start":42,"end":55,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/products/load-balancer/"}}]},{"type":"paragraph","text":"Here's an example of horizontal scaling in a diagram:","spans":[]},{"type":"image","url":"https://images.prismic.io/www-static/76831544fbe08331f8e10fd4bbbf588b62cf2506_horizontal-scaling.png?auto=compress,format","alt":"Horizontal Scaling","copyright":null,"dimensions":{"width":745,"height":290}},{"type":"paragraph","text":"The load balancer has a single responsibility: deciding which server from the cluster will receive a request that was intercepted. It basically acts like a reverse proxy, making the process seamless to the user.","spans":[{"start":156,"end":169,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/community/tutorials/how-to-configure-nginx-as-a-reverse-proxy-for-apache"}}]},{"type":"paragraph","text":"While horizontal scaling is usually the most reliable and efficient method of scalability, it's not as trivial as vertical scaling. In a nutshell, the main challenges of scaling web applications is keeping all the nodes in a cluster updated and synchronized. Consider the following scenario.","spans":[]},{"type":"image","url":"https://images.prismic.io/www-static/2fe03cbc25037e98fd32549bdbef40378f5868f8_scenario.png?auto=compress,format","alt":"Horizontal Scaling","copyright":null,"dimensions":{"width":745,"height":293}},{"type":"paragraph","text":"When user A makes a request to mydomain.com, the load balancer will forward requests to server1. User B, on the other hand, gets forwarded another node from the cluster, server2.","spans":[]},{"type":"paragraph","text":"What happens when user A makes changes to the application, like uploading files or updating content in the database? How do you maintain consistency across all nodes in the cluster? Further, PHP saves session information in disk by default. If user A logs in, how can we keep that user's session in subsequent requests, considering that the load balancer could send them to another server in the cluster?","spans":[]},{"type":"paragraph","text":"Let's discuss what can be done to overcome these issues and prepare your existing PHP application for horizontal scaling.","spans":[]},{"type":"heading2","text":"Decouple, Decouple, Decouple","spans":[]},{"type":"paragraph","text":"Preparing a system for scalability involves a lot of decoupling, because it's essential to have smaller servers with fewer responsibilities instead of one giant, all-inclusive server. This is really the essence of horizontal scaling. Breaking the application down into parts will also help you measure and identify the real bottlenecks you might have.","spans":[]},{"type":"paragraph","text":"Consider a PHP application where users can log in and upload photos. The app uses a basic LAMP stack, and the photos are stored in disk and referenced in the database. The challenge here is to keep consistency between multiple application servers sharing the same data (user uploaded files and user sessions).","spans":[]},{"type":"paragraph","text":"In order to make this example application scalable, there needs to be a separation between web server and database. This way, we can have multiple application nodes sharing the same database server. It's a first step, and it will give the app a small performance improvement by reducing the load of the web server. This tutorial can help you with that.","spans":[{"start":315,"end":328,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/community/tutorials/how-to-set-up-a-remote-database-to-optimize-site-performance-with-mysql"}}]},{"type":"paragraph","text":"For further scalability, you should also consider implementing a load balancing environment for the database. This tutorial shows how to set up a load balancer for a MySQL cluster.","spans":[{"start":110,"end":123,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/community/tutorials/how-to-use-haproxy-to-set-up-mysql-load-balancing--3"}}]},{"type":"heading2","text":"User Session Consistency","spans":[]},{"type":"paragraph","text":"Once the application is isolated from the database server, we can focus on issues specific to the PHP implementation. First, we need to figure out a way for handling the user sessions across the nodes. Let's talk about a few approaches.","spans":[]},{"type":"heading3","text":"Relational Databases and Network Filesystems","spans":[]},{"type":"paragraph","text":"Many people use the approach of saving the session data in relational databases, like MySQL, because it's fairly easy to implement. However, this is a less desirable solution because it adds a substantial overhead (reading and writing to the database for every single request), and in high-traffic incidents, the database is usually the first to go down.","spans":[]},{"type":"paragraph","text":"Similarly, using a network filesystem is another easy solution to implement as it doesn't require any changes to the codebase, but network filesystems are slow for I/O operations (again, reading and writing for each request made) and this might have a negative impact in the application performance.","spans":[]},{"type":"paragraph","text":"Sticky Sessions","spans":[]},{"type":"paragraph","text":"Sticky sessions are implemented in the load balancer and don't require any change in the application nodes, so this is the easiest way to handle user sessions. Sticky sessions make the load balancer always redirect a user to the same server, avoiding the need for sharing session information across nodes.","spans":[]},{"type":"paragraph","text":"However, this solution creates new problems. The load balancer now has more responsibilities, which can impact its performance and turn it into a single point of failure. This approach can also create cold and hot spots within the cluster; returning users will always access the same server, even when new nodes are added to the cluster.","spans":[]},{"type":"heading3","text":"Using a Memcached or Redis Server","spans":[]},{"type":"paragraph","text":"This solution requires setting up one or more additional servers to handle the user sessions, but it's the most reliable way for solving the sessions problem. Both Memcached and Redis are super fast key-value storage engines that provide session handling for PHP. In a nutshell, after setting up the Memcached or Redis server, you will need to configure each node to be able to connect to the server and use it as session handler. This includes installing a PHP extension and making a simple change in the php.ini settings.","spans":[{"start":164,"end":173,"type":"hyperlink","data":{"link_type":"Web","url":"http://memcached.org/"}},{"start":178,"end":183,"type":"hyperlink","data":{"link_type":"Web","url":"http://redis.io/"}}]},{"type":"paragraph","text":"More information about setting up the Memcached session handler for PHP can be found in the official PHP documentation. For Redis, you can find a detailed guide in this link.","spans":[{"start":92,"end":118,"type":"hyperlink","data":{"link_type":"Web","url":"http://php.net/manual/en/memcached.sessions.php"}},{"start":161,"end":173,"type":"hyperlink","data":{"link_type":"Web","url":"http://phpave.com/redis-as-a-php-session-handler/"}}]},{"type":"heading2","text":"User File Consistency","spans":[]},{"type":"paragraph","text":"So far, we've separated our application and database and dealt with the user session consistency problem. We still need to find a solution to keep consistency between the files uploaded by users, because they could be stored in any of the application nodes.","spans":[]},{"type":"paragraph","text":"There are different methods for solving this problem. In some ways it is similar to the user sessions case, but fortunately, it's actually much simpler. The files are not written to or read from disk for each request, which makes the file sharing not as resource intensive. A solution like GlusterFS can work really well here, which creates a shared storage that will replicate any contents saved into one node to other nodes in the cluster. You can find detailed instructions on how to use GlusterFS to set up such an environment in this tutorial.","spans":[{"start":290,"end":299,"type":"hyperlink","data":{"link_type":"Web","url":"http://www.gluster.org/"}},{"start":531,"end":547,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/community/tutorials/how-to-create-a-redundant-storage-pool-using-glusterfs-on-ubuntu-servers"}}]},{"type":"paragraph","text":"Another popular solution is to use object storage to save the files. This can be implemented using different methods, from simple database blob storage to cloud storage services like AWS S3 and Google Cloud Storage. However, it might require a considerable amount of changes to the codebase, depending on how the application is implemented.","spans":[{"start":35,"end":49,"type":"hyperlink","data":{"link_type":"Web","url":"http://en.wikipedia.org/wiki/Object_storage"}},{"start":183,"end":189,"type":"hyperlink","data":{"link_type":"Web","url":"http://aws.amazon.com/s3/"}},{"start":194,"end":214,"type":"hyperlink","data":{"link_type":"Web","url":"https://cloud.google.com/storage/"}}]},{"type":"heading2","text":"Load Balancing","spans":[]},{"type":"paragraph","text":"With the application properly decoupled, it's finally possible to create replica nodes that will compose the app cluster. Our example app now has the following setup:","spans":[]},{"type":"image","url":"https://images.prismic.io/www-static/120f16e988bb674257d6445a4694f7b64932220e_load-balancing.png?auto=compress,format","alt":"Load Balancing","copyright":null,"dimensions":{"width":745,"height":286}},{"type":"paragraph","text":"Both App01 and App02 should be accessible and able to handle requests in the exact same way. The only thing left to do is set up the load balancer to act as the application entry point, redirecting users to the different nodes in the cluster.","spans":[]},{"type":"paragraph","text":"HAProxy (which stands for High Availability Proxy) is the standard open source choice for load balancing. It's used by high-profile environments like Twitter, Instagram, and Imgur. For a better understanding on how HAProxy works and different ways to configure it, check out this introductory tutorial.","spans":[{"start":0,"end":7,"type":"hyperlink","data":{"link_type":"Web","url":"http://www.haproxy.org/"}},{"start":275,"end":301,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/community/tutorials/an-introduction-to-haproxy-and-load-balancing-concepts"}}]},{"type":"paragraph","text":"Another great tutorial from our community explains how to setup HAProxy as load balancer for WordPress servers. It's a good starting point to understand the practical steps necessary to horizontally scale PHP applications.","spans":[{"start":51,"end":110,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/community/tutorials/how-to-use-haproxy-as-a-layer-4-load-balancer-for-wordpress-application-servers-on-ubuntu-14-04"}}]},{"type":"paragraph","text":"Final Considerations","spans":[]},{"type":"paragraph","text":"Preparing an application for horizontal scaling may look intimidating at first, but once you understand how the load balancer works, it gets easier to figure out what steps should be taken in order to get your environment ready for scale.","spans":[]},{"type":"paragraph","text":"Naturally, it's much easier to plan for scalability when you are building an application from scratch, but we don't always have this luxury. It also worth mentioning that scalability walks side by side with performance, but they are not the same thing, and not all applications need to be scalable. Speed, on the other hand, is something all apps can benefit from.","spans":[]},{"type":"paragraph","text":"If you want to learn more, take a look at our YouTube playlist with some of the best talks on PHP performance and scaling, and check out load balancers on DigitalOcean!","spans":[{"start":46,"end":62,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.youtube.com/playlist?list=PLseEp7p6EwiaiJx-AZqXgvpJNJgXuNeBx"}},{"start":137,"end":151,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/products/load-balancer/"}}]},{"type":"paragraph","text":"by Erika Heidi","spans":[{"start":3,"end":14,"type":"hyperlink","data":{"link_type":"Web","url":"https://twitter.com/erikaheidi"}}]}],"blog_post_date":"2015-04-21","tags":[{"tag1":{"tag":"Engineering","_linkType":"Link.document","_meta":{"uid":"engineering"}}}],"_meta":{"uid":"horizontally-scaling-php-applications"}}},{"node":{"author":{"_linkType":"Link.document","author_name":"Erika Heidi","author_image":null,"_meta":{"uid":"erika_heidi"}},"blog_header_image":{"dimensions":{"width":750,"height":400},"alt":"FreeBSD is here text on illustration with red converse style shoes, a pitchfork, and a devil tail","copyright":null,"url":"https://images.prismic.io/www-static/a0978ef23fa5a14b22c2180b4c40c755e5960a93_freebsd-blog.png?auto=compress,format"},"blog_headline":[{"type":"heading1","text":"Presenting FreeBSD! How We Made It Happen.","spans":[]}],"blog_post_content":[{"type":"paragraph","text":"We're happy to announce that FreeBSD is now available for use on DigitalOcean!","spans":[]},{"type":"paragraph","text":"FreeBSD will be the first non-Linux distribution available for use on our platform.  It's been widely requested because of its reputation of being a stable and performant OS.  While similar to other open source unix-like operating systems, it's unique in that the development of both its kernel and user space utilities are managed by the same core team, ensuring consistent development standards across the project.  FreeBSD also offers a simple, yet powerful package management system that allows you to compile and install third-party software for your system with ease.","spans":[]},{"type":"paragraph","text":"One particularly compelling attribute of the FreeBSD project is the quality of their documentation, including the FreeBSD Handbook which provides a comprehensive and thoughtful overview of the operating system.  We at DigitalOcean love effective and concise technical writing, and so we've also produced numerous FreeBSD tutorials to aid new users with Getting Started with FreeBSD.","spans":[{"start":85,"end":98,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.freebsd.org/docs.html"}},{"start":114,"end":130,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/"}},{"start":304,"end":330,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/community/tags/freebsd?primary_filter=tutorials"}},{"start":353,"end":381,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.digitalocean.com/community/tutorials/how-to-get-started-with-freebsd-10-1"}}]},{"type":"paragraph","text":"We understand that this has been a long standing user request, and we've heard you.  You might be asking yourself - what took so long?","spans":[]},{"type":"paragraph","text":"The internal structure of DigitalOcean's engineering team has rapidly changed over time due to the dynamic growth of the company.  What began as a couple of guys coding furiously in a room in Brooklyn has ballooned to a 100+ person organization serving hundreds of thousands of users around the globe.  As we've grown, by necessity we've needed to adjust and reorganize ourselves and our systems to be able to better serve our users.  There have been many experiments in how we approach, prioritize and execute this work; this image is a result of the successful alignment of a few key elements.","spans":[]},{"type":"heading3","text":"Technical Foundation","spans":[]},{"type":"paragraph","text":"Last year, we built our metadata service — allowing a droplet to have access to information about itself at the time that it's being created.  This is a powerful thing because it gives a vanilla image a mechanism to configure itself independently.  This service was a big part what allowed us to offer CoreOS, and in building it, it gave us more flexibility in what we could offer moving forward.  Our backend code would no longer need to know the contents of the image to be able to serve it.  On creation, the droplet itself could query for configurables — hostnames, ssh keys, and the like —  and configure itself instead of relying on a third party.","spans":[]},{"type":"paragraph","text":"This fundamental decoupling is an echo of a familiar refrain: build well defined interfaces and don't let knowledge leak across those boundaries unnecessarily.  It's allowed us to free images from customization by our backend code, and entirely sidestep the problematic issue of modifying a UFS filesystem from a Linux host.","spans":[]},{"type":"paragraph","text":"Since we now had a feasible mechanism to allow images to be instantiated independently of our backend, we just needed to put the parts together that would allow us to inject the configuration upon creation.  FreeBSD doesn't itself offer cloud versions of the OS similar to what Canonical and Red Hat provide, so we started from a publicly available port of cloud-init meant to allow FreeBSD to run on OpenStack.","spans":[{"start":349,"end":367,"type":"hyperlink","data":{"link_type":"Web","url":"http://pellaeon.github.io/bsd-cloudinit/"}}]},{"type":"paragraph","text":"In order to query metadata, we need to have an initial network configuration in order to build our configuration, since DigitalOcean's droplets use static networking.  During boot time, we bring up the droplet on a v4 link-local address in order to do the initial query to the service.  From there, we pick up the real network config, hostname, and ssh keys.  The cloud-init project then writes a configuration that's associated with the droplet's ID.  Linking this configuration to the droplet ID is the mechanism that allows it to know whether the image is being created from a snapshot or new create, or is just a rebooted instance of an already configured droplet.","spans":[]},{"type":"paragraph","text":"Once this configuration has been injected, FreeBSD's boot process can continue and use it accordingly — eventually booting into the instance as expected.","spans":[]},{"type":"heading3","text":"Focus","spans":[]},{"type":"paragraph","text":"This endeavor began life as an experiment in how we organize ourselves in the engineering team.  We were given a few weeks to pick a project, self organize in cross-functional teams, and execute.  A lot went right during this process that allowed this project to succeed.","spans":[]},{"type":"paragraph","text":"Deadlines are powerful things.  Not in a punitive or negative sense of the word, but in a sense that there will be a well defined time where work on this will collectively end.  So is having a very clear picture of what \"done\" looks like.  In the case of BSD, it was particularly powerful to have a clear goal of a alpha functional BSD droplet with a date to drive for.  Given the freedom to focus on a single goal, clear communication, and well defined restraints, we were able to finally deliver a long standing user request with relative ease.","spans":[]},{"type":"paragraph","text":"This is the start to the many things we're excited to build in 2015!","spans":[]},{"type":"paragraph","text":"By: Neal Shrader","spans":[{"start":4,"end":16,"type":"hyperlink","data":{"link_type":"Web","url":"https://twitter.com/icosahedral"}}]}],"blog_post_date":"2015-01-13","tags":[{"tag1":{"tag":"Product Updates","_linkType":"Link.document","_meta":{"uid":"product-updates"}}},{"tag1":{"tag":"Engineering","_linkType":"Link.document","_meta":{"uid":"engineering"}}},{"tag1":{"tag":"News","_linkType":"Link.document","_meta":{"uid":"news"}}}],"_meta":{"uid":"presenting-freebsd-how-we-made-it-happen"}}},{"node":{"author":{"_linkType":"Link.document","author_name":"Erika Heidi","author_image":null,"_meta":{"uid":"erika_heidi"}},"blog_header_image":{"dimensions":{"width":750,"height":400},"alt":"php thank you","copyright":null,"url":"https://images.prismic.io/www-static/0d34a56c-8cc0-4df2-b91a-b6a9a72a031c_php-thanks.png?auto=compress,format"},"blog_headline":[{"type":"heading1","text":"Thank You To PHP's Top Package Authors!","spans":[]}],"blog_post_content":[{"type":"paragraph","text":"PHP remains the most popular server-side programming language powering the world wide web and in use by 82% of websites. Metrics focused on server-side languages show that PHP usage has increased by 1% in the past year alone.","spans":[{"start":16,"end":28,"type":"hyperlink","data":{"link_type":"Web","url":"http://w3techs.com/technologies/overview/programming_language/all"}},{"start":121,"end":128,"type":"hyperlink","data":{"link_type":"Web","url":"http://w3techs.com/technologies/history_overview/programming_language"}}]},{"type":"paragraph","text":"Much of the growth in the last few years was driven by recently developed tools and frameworks, especially Composer. Composer is a dependency management tool, similar to Node's npm, that manages per-project dependencies and package versions for PHP projects. It uses Packagist as its main package repository, which has shown impressive growth in the last year, doubling the number of tracked packages.  This past October, the number of installations, themselves, reached the 45 million mark.","spans":[{"start":107,"end":115,"type":"hyperlink","data":{"link_type":"Web","url":"https://getcomposer.org/"}},{"start":170,"end":180,"type":"hyperlink","data":{"link_type":"Web","url":"https://www.npmjs.org/"}},{"start":267,"end":276,"type":"hyperlink","data":{"link_type":"Web","url":"https://packagist.org/"}},{"start":325,"end":342,"type":"hyperlink","data":{"link_type":"Web","url":"https://packagist.org/statistics"}}]},{"type":"paragraph","text":"As such, Mikeal and Erika from the DigitalOcean Evangelism team, were curious to find the top 10 Packagist contributors based on the 50 most required packages and their authors. We used this script to collect our data.","spans":[{"start":9,"end":15,"type":"hyperlink","data":{"link_type":"Web","url":"https://twitter.com/mikeal"}},{"start":20,"end":25,"type":"hyperlink","data":{"link_type":"Web","url":"https://twitter.com/erikaheidi"}},{"start":133,"end":158,"type":"hyperlink","data":{"link_type":"Web","url":"https://github.com/mikeal/php-analytics/blob/master/top50-packages.md"}},{"start":186,"end":197,"type":"hyperlink","data":{"link_type":"Web","url":"https://github.com/mikeal/php-analytics"}}]},{"type":"paragraph","text":"Why the most required packages? Open source project authors rely on libraries that are well-maintained and stable.  These provide a solid structure on which to build a successful project. If hundreds or thousands of projects are relying on a specific package, this will also mean more people able to contribute and quickly fix any bugs that might show up in the underlying required library.","spans":[]},{"type":"paragraph","text":"Thus, we'd like to give a huge thank you to the authors who took their time to create and share awesome projects with the open source community!","spans":[{"start":31,"end":40,"type":"strong"}]},{"type":"heading3","text":"1) Fabien Potencier  – 22 packages, 16412  total references","spans":[{"start":3,"end":19,"type":"hyperlink","data":{"link_type":"Web","url":"https://twitter.com/fabpot"}}]},{"type":"paragraph","text":"Fabien Potencier leads the ranking with 22 packages being referenced (required) by a total of 16412 other packages. Most part of these packages are components of the Symfony Framework, created by Fabien, which are also widely used together or isolated in other projects. His most required package is symfony/framework-bundle with 2626 packages depending on it. This package is a requirement for Symfony bundles, which basically extends the main framework's functionality.","spans":[{"start":300,"end":324,"type":"hyperlink","data":{"link_type":"Web","url":"https://packagist.org/packages/symfony/framework-bundle"}}]},{"type":"heading3","text":"2) Sebastian Bergman – 1 package, 9181 total references","spans":[{"start":3,"end":20,"type":"hyperlink","data":{"link_type":"Web","url":"https://twitter.com/s_bergmann"}}]},{"type":"paragraph","text":"Sebastian Bergman is the author of phpunit/phpunit, the most referenced package on Packagist. PHPUnit is a popular unit testing framework for PHP, used as a development requirement by 9181 other projects of all sizes and types on Packagist.","spans":[{"start":35,"end":50,"type":"hyperlink","data":{"link_type":"Web","url":"https://packagist.org/packages/phpunit/phpunit"}},{"start":94,"end":101,"type":"hyperlink","data":{"link_type":"Web","url":"https://phpunit.de/"}}]},{"type":"heading3","text":"3) Taylor Otwell – 3 packages, 3608 total references","spans":[{"start":3,"end":16,"type":"hyperlink","data":{"link_type":"Web","url":"https://twitter.com/taylorotwell"}}]},{"type":"paragraph","text":"Taylor Otwell is the creator of the Laravel Framework. His package illuminate/support is the second most required on Packagist, with 3608 projects depending on it. This library offers a series of helpers for dealing with databases, arrays, and collections. It is a component of the Laravel Framework but can also be used as a standalone library.","spans":[{"start":36,"end":53,"type":"hyperlink","data":{"link_type":"Web","url":"http://laravel.com/"}},{"start":67,"end":85,"type":"hyperlink","data":{"link_type":"Web","url":"https://packagist.org/packages/illuminate/support"}}]},{"type":"heading3","text":"4) Benjamin Eberlei – 4 packages, 3170 total references","spans":[{"start":3,"end":19,"type":"hyperlink","data":{"link_type":"Web","url":"https://twitter.com/beberlei"}}]},{"type":"paragraph","text":"Benjamin Eberlei is the lead of the Doctrine project, a collection of several PHP libraries focused on database abstraction and object mapping. The package doctrine/orm is the most required, with 1421 other packages depending on it. Those include frameworks, CMSs, and various database-related libraries.","spans":[{"start":36,"end":52,"type":"hyperlink","data":{"link_type":"Web","url":"http://www.doctrine-project.org/"}},{"start":156,"end":168,"type":"hyperlink","data":{"link_type":"Web","url":"https://packagist.org/packages/doctrine/orm"}}]},{"type":"heading3","text":"5) Jordi Boggiano – 2 packages, 1975 total references","spans":[{"start":3,"end":17,"type":"hyperlink","data":{"link_type":"Web","url":"https://twitter.com/seldaek"}}]},{"type":"paragraph","text":"Jordi Boggiano is the co-author of Composer, the project that inspired this article and stands as one of the most relevant milestones in modern PHP. Jordi is one of the authors of composer/installers, and he also created monolog/monolog. The former is commonly required by frameworks and CMSs to bring composer features into those projects, and the latter is a very popular logging library for PHP.","spans":[{"start":35,"end":43,"type":"hyperlink","data":{"link_type":"Web","url":"https://getcomposer.org/"}},{"start":180,"end":199,"type":"hyperlink","data":{"link_type":"Web","url":"https://packagist.org/packages/composer/installers"}},{"start":221,"end":236,"type":"hyperlink","data":{"link_type":"Web","url":"https://packagist.org/packages/monolog/monolog"}}]},{"type":"heading3","text":"6) Pádraic Brady – 1 package, 1660 total references","spans":[{"start":3,"end":16,"type":"hyperlink","data":{"link_type":"Web","url":"https://twitter.com/padraicb"}}]},{"type":"paragraph","text":"Pádraic Brady is the author of mockery/mockery, a mock object framework for unit testing in PHP. As with PHPUnit, this is usually a development requirement for creating and running the project test suite. It's required by 1660 other packages on Packagist.","spans":[{"start":31,"end":46,"type":"hyperlink","data":{"link_type":"Web","url":"https://packagist.org/packages/mockery/mockery"}}]},{"type":"heading3","text":"7) Zend Framework – 2 packages, 1453 total references","spans":[{"start":3,"end":17,"type":"hyperlink","data":{"link_type":"Web","url":"https://twitter.com/zfdevteam"}}]},{"type":"paragraph","text":"Zend is a popular framework for PHP. The Zend Framework development team has two packages in the TOP 50, the most required one being zendframework/zendframework with 1123 packages depending on it. Between the dependant packages are components of the main framework, as well as many extensions created by users.","spans":[{"start":133,"end":160,"type":"hyperlink","data":{"link_type":"Web","url":"https://packagist.org/packages/zendframework/zendframework"}}]},{"type":"heading3","text":"8) Kitamura Satoshi – 1 package, 1371 total references","spans":[{"start":3,"end":19,"type":"hyperlink","data":{"link_type":"Web","url":"https://github.com/satooshi"}}]},{"type":"paragraph","text":"Kitamura Satoshi is the author of satooshi/php-coveralls, a PHP client library for Coveralls – an application that basically provides test coverage stats for continuous integration environments.This library is required by 1371 other projects on Packagist as it is a popular asset for continuous integration within PHP projects.","spans":[{"start":34,"end":56,"type":"hyperlink","data":{"link_type":"Web","url":"https://packagist.org/packages/satooshi/php-coveralls"}},{"start":83,"end":92,"type":"hyperlink","data":{"link_type":"Web","url":"https://coveralls.io/"}}]},{"type":"heading3","text":"9) Michael Dowling – 2 packages, 1329 total references","spans":[{"start":3,"end":18,"type":"hyperlink","data":{"link_type":"Web","url":"https://twitter.com/mtdowling"}}]},{"type":"paragraph","text":"Michael Dowling is the creator of Guzzle, a HTTP client library and framework for PHP. This library is very popular with projects that make use of remote APIs. His package guzzle/guzzle is required by other 811 projects on Packagist, and many of those are wrapper libraries created to facilitate the use of various APIs.","spans":[{"start":34,"end":40,"type":"hyperlink","data":{"link_type":"Web","url":"http://docs.guzzlephp.org/en/latest/"}},{"start":172,"end":185,"type":"hyperlink","data":{"link_type":"Web","url":"https://packagist.org/packages/guzzle/guzzle"}}]},{"type":"heading3","text":"10) Greg Sherwood – 1 package, 1264 total references","spans":[{"start":4,"end":17,"type":"hyperlink","data":{"link_type":"Web","url":"https://twitter.com/gregsherwood"}}]},{"type":"paragraph","text":"Greg Sherwood is the author of squizlabs/php_codesniffer, a library for detecting violations according to a defined code standard. His package is required by 1264 other projects on Packagist.","spans":[{"start":31,"end":56,"type":"hyperlink","data":{"link_type":"Web","url":"https://packagist.org/packages/squizlabs/php_codesniffer"}}]},{"type":"paragraph","text":"by Erika Heidi","spans":[{"start":3,"end":14,"type":"hyperlink","data":{"link_type":"Web","url":"https://twitter.com/erikaheidi"}}]}],"blog_post_date":"2014-11-25","tags":[{"tag1":{"tag":"Engineering","_linkType":"Link.document","_meta":{"uid":"engineering"}}},{"tag1":{"tag":"Community","_linkType":"Link.document","_meta":{"uid":"community"}}}],"_meta":{"uid":"thank-you-to-phps-top-package-authors"}}}]}}}