Wednesday, October 29, 2014

Packaging your Box in Vagrant

  • Set up your virtual machine
    • vagrant up
      
  • List your virtual machines
    • $ VBoxManage list vms
      "tesselact_default_1413389341047_169" {7ca66929-48d7-4e36-9237-011b5113c07b}
      "php-salt-box_default_1414574460667_45040" {a872c748-bf3f-46e1-9cd7-db7b7c1b302d}
      
  • Create the package
    • vagrant package --base php-salt-box_default_1414574460667_45040
      
  • You'll find your packaged box in a package.box file

Tuesday, September 9, 2014

Unit test / Test doubles

Test doubles
"Test Double is a generic term for any case where you replace a production object for testing purposes" - Martin Fowler
  • Dummy
    • What does it do?
      • It does almost nothing. You just need it (for example) to pass as a parameter to a constructor.
    • Example?
      • A dummy class has a method which returns null.
  • Stub
    • What does it do?
      • Kind of dummy. It does a thing. It returns a specific value.
    • Example?
      • A stub class has a method which returns true.
  • Spy
    • What does it do?
      • Kind of stub. Saves any kind of things what you might need to check at the end of your test.
    • Example? 
      • A spy class saves whether its "foobar" method has been called.
  • Mock
    • What does it do?
      • Kind of spy. Does behavioural testing. It knows what behaviour is expected. What function was called, with what arguments, when and how many times.
    • Example?
      • A mock expects the "validate" method will run 2 times and will return true.
  • Fake
    • What does it do?
      • Business behavioural testing. It can return different values based on different parameters.
    •  Example?
      • A fake class has a method which returns true if the logged in user's name (a parameter) is "root" else returns false.
 
It is beneficial to read uncle Bob's article.

References
http://blog.8thlight.com/uncle-bob/2014/05/14/TheLittleMocker.html

Thursday, August 21, 2014

Set up a Symfony2 dev environment in 10 minutes with Vagrant

Let's keep it simple. It is just a quick draft how can you set up a Symfony2 development environment in a few minutes.

I'll use Vagrant (you'll need version 1.5 at least) and my dev box to create the desired environment.

The box main components are: Ubuntu14.04, Nginx1.6, Php5.5Fpm, Xdebug, Composer, MySql5.5, NodeJs0.10.30, Redis and it has PhpMyAdmin, Webgrind and RedisCommander.

So the steps are:
  • Create the Vagrantfile
    # -*- mode: ruby -*-
    # vi: set ft=ruby :
    
    VAGRANTFILE_API_VERSION = "2"
    
    Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
      config.vm.box = "adammbalogh/lemp"
    
      config.vm.network "private_network", ip: "192.168.33.10"
      config.vm.synced_folder "app/", "/var/www/app/"
    
      config.vm.provider "virtualbox" do |vb|
        vb.customize ["modifyvm", :id, "--memory", "1512"]
        vb.customize ["modifyvm", :id, "--cpuexecutioncap", "85"]
      end
    end
    
    
  • mkdir app
  • vagrant up
  • vagrant ssh
  • cd /var/www/app
  • composer create-project symfony/framework-standard-edition . '~2.5'
  • nano app/AppKernel.php (and add these two methods)
    public function getCacheDir()
    {
        return '/tmp/symfony/cache/' . $this->environment;
    }
    
    public function getLogDir()
    {
        return '/tmp/symfony/log/' . $this->environment;
    }
    
  • nano web/app_dev.php (and delete these lines)
    if (isset($_SERVER['HTTP_CLIENT_IP'])
        || isset($_SERVER['HTTP_X_FORWARDED_FOR'])
        || !(in_array(@$_SERVER['REMOTE_ADDR'], array('127.0.0.1', 'fe80::1',$
    ) {
        header('HTTP/1.0 403 Forbidden');
        exit('You are not allowed to access this file. Check '.basename(__FIL$
    }
    
  • app/console cache:clear --env=dev (to test it)

Thursday, August 7, 2014

Connect a Usb device through Vagrant

If you want to list your usb devices do this:
$ VBoxManage list usbhost
Host USB Devices:

<none>
On a pure VirtualBox setup it says nothing. Usb devices won't work in your virtual machine until you don't see something in the list. So, you'll need to do two things to fix this:

  • Install VirtualBox Extension Pack (from here)
  • You have to be (your currently logged in user) in the vboxusers group
    • sudo usermod -a -G vboxusers <username>
    • and you have to logout/login from your session!

When you have done with these steps, run the list usbhost again:
$ VBoxManage list usbhost
Host USB Devices:

UUID:               55d6661d-dd23-487c-8f97-23d4cd4f7378
VendorId:           0x064e (064E)
ProductId:          0x8125 (8125)
Revision:           40.16 (4016)
Port:               4
USB version/speed:  2/2
Manufacturer:       SuYin
Product:            Laptop_Integrated_Webcam_HD
Address:            sysfs:/sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.5//device:/dev/vboxusb/001/004
Current State:      Busy

UUID:               e96c6aef-f8a7-4f18-a67e-07776c7d839e
VendorId:           0x0bda (0BDA)
ProductId:          0x0129 (0129)
Revision:           57.96 (5796)
Port:               2
USB version/speed:  2/2
Manufacturer:       Generic
...

In Vagrantfile you have to enable the usb option and add a filter based on the desired Manufacturer and Product:
config.vm.provider "virtualbox" do |vb|
  ...
  vb.customize ["modifyvm", :id, "--usb", "on"]
  vb.customize ["modifyvm", :id, "--usbehci", "on"]
  vb.customize ["usbfilter", "add", "0", 
    "--target", :id, 
    "--name", "This is the identifier",
    "--manufacturer", "SuYin",
    "--product", "Laptop_Integrated_Webcam_HD"]
  ...
end  
You are all set.

Run vagrant up and ssh in your vm with vagrant ssh. In your vm run lsusb and you should see the connected usb device!

Wednesday, July 9, 2014

Upstart

If you have ever have a problem with php forking, upstart will be your good friend.

What is upstart?
In short: service management daemon

"Upstart is an event-based replacement for the /sbin/init daemon which handles starting of tasks and services during boot, stopping them during shutdown and supervising them while the system is running."

Let's make it clear (from our perspective):
You can start any of your (php) scripts as a daemon (even with arguments) with a handy toolset: status / start / stop / restart

Config your job (e.g. a script)
Pretend that you have a my-awesome-app.php, which you want to start as daemon on every system boot. Your script can easily become fragile, so you also want to monitor it with a respawn mechanism.

First, you have to create an upstart config and place it in the /etc/init directory. In this case it will be this one: /etc/init/my-awesome-app.conf

# /etc/init/my-awesome-app.conf
description "daemonized awesome app"
version "1.0"
author "adammbalogh"

# restart my app on a crash
respawn
# stop restarting my app if it crashes more than 5 times in 30 sec
respawn limit 5 30

# start my script after nginx started
start on started nginx
# stop it on system shutdown
stop on runlevel S

# run as user and group
setuid www-data
setgid www-data

script
  exec php /home/user/public_html/my-awesome-app.php
end script

After you've created this conf file, just start your app with upstart: sudo start my-awesome-app.conf

Misc
You can also create pre or post scripts with a simple statement.

pre-start script
  exec touch /tmp/myapp.log
end script

If you want to use configuration variable you can do it too.

env BYE=goodbye
post-start script
  exec echo $BYE >> /tmp/myapp.log
end script

Finally, a useful cmd which lists all jobs and their states: initctl list

Monday, July 7, 2014

Web and Cli Debugging with PhpStorm, XDebug in Vagrant

We've a Vagrant box in a development environment and want to debug our application. Take a quick review of the two main ways, so it can be either a web app or a cli based app.


Web app debugging
First, we have to create a Server configuration:

File -> Settings -> Php -> Servers

Server configuration

Add a new server with its ip address (or hostname) and set the desired port. Check "Use path mappings" and map the vagrant's paths to the local ones.

The next step is creating a Run/Debug configuration:

Run -> Edit Configurations

Run/Debug configuration

Add a "PHP Web Application" config. Give it a name and choose the previously configured server from the select box.

To run our app in debug mode just go to:

Run -> Debug

and the web app will appear on a new tab in debug mode! If you want to restart the debug session again (after the actual one is disconnected) just refresh the page in the browser.

Cli app debugging:
At the start we should able to reach the host machine from our Vagrant box. So, how can we find out the host's ip?
"The IP address of the host is always the same IP address but with the final octet as a 1."
Okay, e.g.: if the vbox's ip is 192.168.33.10 we can ping 192.168.33.1 as our host machine from our guest.

We need the Server configurations as well (the same as the Web app debugging).

On the server side (in Vagrant) we've to create some environment variables:

export PHP_IDE_CONFIG="serverName=phpsaltbox"

export XDEBUG_CONFIG="remote_host=192.168.33.1 idekey=phpsaltbox"

serverName is the name what we typed in the Server configurations.
idekey comes from the xdebug config xdebug.idekey (it can be anything).

To run our cli app in debug mode we'll use the "Start Listen PHP Debug Connections" function in PhpStorm.

"Start Listen PHP Debug Connections" function


As the final step, just run your cli app in Vagrant and you'll see the debug window in PhpStorm in a couple of seconds!


References:

Friday, July 4, 2014

Swap File for low end dev servers

I have a Digital Ocean Vps, but only for hobby projects. So it has merely 512Mb memory. If you want
to run multiple applications on a small development server you can operate with more memory, just use swap files.


"Swap space will allow the operating system to temporarily move data from memory onto the disk when the amount of information in memory exceeds the physical memory space available"

Of course it will be much slower. Fortunately D.Ocean has only Ssd hard drives, so Ssd improves the situation.

Here are the bash lines from a Digital Ocean article:

sudo fallocate -l 1G /swapfile; sudo mkswap /swapfile; sudo swapon /swapfile

Create an empty 1Gb file; Format to swap space; Enable it
This swap file remains until the next reboot!

Sunday, June 1, 2014

How should I build a RESTful API? /Act II. - Is your API mature enough?/

After Act I. we know the basics of the REST architectural style. Before start the development process we should take a look at an important Model, which is a kinda de-facto to measure how RESTful is an API.

That is the Richardson Maturity Model. This model also helps us to see a big picture of how should look our API in a way of RESTful.

Let's take a look at Martin Fowler's explanation.



REST has a Uniform Interface, which does not have to be the HTTP, but we're web developers so we'll use HTTP as our Uniform Interface!


Level 0 - The Swamp of POX (Plain Old Xml):

At Level 0 we use HTTP as a tunnel to Remote Interactions. We use only one entry point (URI) and one kind of HTTP method (e.g. POST). Examples: SOAP, XML-RPC, JSON-RPC


Level 1 - Resources:
Now we use multiple entry points (URIs), which are unique identifiers to retrieve resources. This level still uses only one HTTP method. Examples: http://api.example.com/cars, http://api.example.com/cars/1, http://api.example.com/cars/2


Level 2 - HTTP Verbs:
At Level 2 we proudly introduce multiple HTTP verbs. Use GET for read a resource, DELETE to delete it and so on (anyway REST != CRUD).
Another important principle is that the usage of the proper HTTP response codes to indicate status. Do not rely always the response 200 (OK), we should be more sophisticated and should toss our almost RESTful API toward a semantic web.
Examples: After a resource creation the proper HTTP response code is the 201 (Created)


Level 3 - Hypermedia Controls:
Hypertext As The Engine Of Application State (HATEOAS). This is the highest level. Without reaching this level our API is not RESTful!
Hypermedia controls are URIs attached to a given resource. These controls tell us what can we able to do next with the resource (e.g. add a related resource to it). One of the main benefit is that it allows us to change the URI schemes without breaking the clients. Another one is that it helps to explore the API.
Examples: go to Martin Fowler's explanation


References:
http://nirmata.com/2013/10/rest-apis-part-1/
http://martinfowler.com/articles/richardsonMaturityModel.html

Thursday, May 22, 2014

How should I build a RESTful API? /Act I. - What is REST?/

To understand what is a RESTful API, first we have to clear what is REST. (this post is far away from a full review of REST, just a quick one to help building a RESTful API, you can find deeper reviews among the references [at the bottom])

REST = REpresentational State Transfer
The elaboration of REST is a part of Roy Fielding's Dissertation

So, what is REST?
Architectural style for distributed hypermedia systems such as World Wide Web
So, REST is an architectural style. Not identical to HTTP, not an API and it's not just one and only for APIs. It is a set of constraints to build a simplified and decoupled system such as Web.

But we want to create an API in REST style, so we'll use the REST constraints to achieve our goal!

Before move on the architectural constraints, first we should take a quick look at the architectural elements.

Architectural elements: (just a minimal representation)
  • Data elements
"The key aspect of REST is the state of the data elements, its components communicate by transferring representations of the current or desired state of data elements"
    • Resources 
      • "Any information that can be named can be a resource: a document or image, a temporal service (e.g. "today's weather in Los Angeles"), a collection of other resources, a non-virtual object (e.g. a person), and so on"
    • Representations 
      • "It is something that is sent back and forth between clients and servers"
      • "Never send or receive resources, only their representations"
      • "Sequence of bytes, HTML document, archive document, image document"
      • Part (it can be the entire) of the resource state
 Architectural constraints:
  • Uniform interface
Defines the Interface between Client and Server. Simplifies and Decouples the Architecture. Uniform interface has 4 constraints:
    • Identification of Resources
      • "Resources must have a unique identifier which can be use to retrieve a resource (e.g. URI)"
    • Manipulation of Resources through Representations
      • "Resources can be updated (or added) by sending representations from the client to the server"
    • Self-descriptive messages
      • "It means each message contains all the information necessary to complete the task"
    • Hypermedia As The Engine Of Application State
      • HATEOAS
      • "The ability to navigate resources through hyperlinks/hypermedia is the hallmark of REST" 
  • Layered system 
    • A client cannot rely a direct connection to the end server
    • There can be intermediary layers between the client and the end server
    • An intermediary can be a load-balancer or proxy...
  • Client-Server
    • Separation of concerns
      • Improves client portability
      • Server can be simpler, more scalable
  • Stateless
    • "each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server"
  • Cacheable
    • "the data within a response to a request be implicitly or explicitly labeled as cacheable or non-cacheable"
  • Code on demand (optional)
    • "server can extend the client functionaility by sending back scripts or code"
    • The code is the know-how to process the representation of the given resource

Next time we'll move on the discussion of a RESTful API!
 
References:
http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm 
http://blog.restlet.com/tag/rest-api/
http://www.slideshare.net/kjbuckley/doing-rest-right-3385800
http://www.sitepen.com/blog/2010/05/09/resource-oriented-programming/
http://mrbool.com/rest-architectural-elements-and-constraints/29339
http://nirmata.com/2013/10/rest-apis-part-1/
http://exyus.com/articles/rest-the-short-version/

Monday, May 12, 2014

Symfony2 - DataFixtures

Fixtures are used to load a controlled set of data into a database. This data can be used for testing or could be the initial data required for the application to run smoothly (from symfony.com)
So, the DataFixture Bundle is a great way to help initialize your application, e.g. set up an admin user. You can use it all through the development phase continuously, it has an append option. Without the append argument your database will be erased before the fixtures get injected.

If you plan to use this bundle for testing, you can mix it up with the Faker library to create various test data.

When you work on a not so large project it's a good enough bundle to solve your problems. But if the project is a large one and you want to use a more sophisticated way to make fixtures you should use the Alice library! (it has a Bundle for Symfony2 -> AliceBundle)

Alice calls itself an Expressive fixtures generator. It has a lot of handy tools in its toolbox.

You can create fixtures in a config file! Let's see a Static one:
Nelmio\Entity\User:
    user0:
        username: bob
        fullname: Bob
        birthDate: 1980-10-10
        email: bob@example.org
        favoriteNumber: 42
    user1:
        username: alice
        fullname: Alice
        birthDate: 1978-07-12
        email: alice@example.org
        favoriteNumber: 27

Nelmio\Entity\Group:
    group1:
        name: Admins
Take a look at a Fixture Range config:
Nelmio\Entity\User:
    user{1..10}:
        username: bob
        fullname: Bob
        birthDate: 1980-10-10
        email: bob@example.org
        favoriteNumber: 42
The above fixture configuration ends up 10 users, from user1 to user10.

It integrates with the Faker library initially and has a several other helpful features.

Tuesday, March 11, 2014

Prologue

Just a new programming blog. And what is this blog about? In nutshell: Php, Java, and related Frameworks!…