CasperJs not working in web browser on Homestead and HHVM

I encountered an annoying error where casperjs / phantomjs was working correctly from the command line, but not working via the browser on my vagrant homestead/hhvm box. After a couple of frustrating hours (more like 4) of checking everything I discovered it is related to permissions.

Ensure that your web user has permissions to run the script in question by adding it to the sudoers file, via ‘visudo’.

Edit:

sudo visudo

Add:

vagrant ALL=NOPASSWD: /usr/bin/phantomjs
vagrant ALL=NOPASSWD: /usr/bin/casperjs

Where ‘vagrant’ is the name of the user your web server runs as. Check the paths to your phantomjs and casperjs.

Restart HHVM (there are some weird issues re: caching and running these scripts, turned opcache off did not help)

service hhvm restart

Make sure you run your script as the web user you gave the permissions to, so:

$command = "sudo -u vagrant /usr/bin/casperjs /my/ur/to/casper/javascript/file.js --url=$url 2>&1";

The scripts I used to test everything was working…

Test.php

<?php

$url = "http://www.bing.com";
var_dump( getCasperData($url));

function getCasperData($url)
{
    putenv("PHANTOMJS_EXECUTABLE=/usr/bin/phantomjs");

    // Check your path to test.js is correct
    $command = "sudo -u vagrant /usr/bin/casperjs test.js --url=$url 2>&1";
    exec($command, $output);
    return implode($output);
}

test.js

//  Tell phantom where casper is.  Check this matches your paths.
phantom.casperPath = '/usr/lib/node_modules/casperjs/';

//  Get the url from args
var system = require('system');
var args = system.args;

// Injext the path into phantom
phantom.injectJs(phantom.casperPath + 'bin/bootstrap.js');

// Use utils module to access various methods
var utils = require('utils');

//  Fire up casper session don't use this when running a test (as below) /usr/bin/casperjs test test.js
var casper = require('casper').create();
var url = casper.cli.get("url");  //casper.echo(casper.cli.get("url"));  //var url = args[3];

//  Test with a casper call.
casper.start(url);

//  Put a wait on the request so it can load the new items.
casper.wait(200, function() {
    this.echo(this.getPageContent());
});

// Function to close the application
casper.then(function() {
    casper.exit();
});

//  Actually run the script
casper.run();

Tinker

php artisan tinker

Eloquent::unguard();

use App\Post, App\Activity, App\Comment;
Post::truncate();

Post::create(['title'=>'Newest title', 'body'=>'Some new body again', 'user_id' => '1']);
Comment::create(['user_id'=>1, 'post_id'=>1, 'body'=>'My first comment!']);

Comment::first()->body;  // My first comment

Activity::all()->toArray();
Post::all()->toJson();
Activity::all()->count();

Post::find(1)->delete();

MySql

Basics

mysql -u root -ppassword
mysql -u root -ppassword kphp //  use kphp db immediately
mysql -u root -password=password

//  default character set and ordering (collation)
//  ci means character insensitive collation
create database kphp CHARACTER SET utf8 COLLATE utf8_general_ci;   

show databases;
use mydb;
show tables;
describe mytable;

CREATE TABLE category (
id INT PRIMARY KEY AUTO_INCREMENT,
name varchar(300)
) ENGINE = INNODB;

insert into category (name) VALUES ('Sports');
insert into category (name) VALUES ('Technology');
insert into category (name) VALUES ('News');

CREATE TABLE post (
id INT PRIMARY KEY AUTO_INCREMENT, 
title varchar(300), 
content TEXT, 
category_id, INT) ENGINE = INNODB;

DROP TABLE IF EXISTS post;
DROP TABLE IF EXISTS category;

UNIX Basics

Absolute Basics

Passwords

passwd

Kill and Processes

kill {processid}

// Find pid
pidof httpd

Superuser

su
sudo -i

Processes

// All processes
ps -e

// Specific user
ps -u root

OS Details

uname
uname -a

// Kernel
uname -s
// Machine architecture
uname -m

Users

who
whoami

Compressed files

gzip textfile  // Compress
gzip -l  // Gzip list
gzip -d textfile.gz  // Decompress

tar -xzvf textfile.tar.gz // Extract tarball
tar -czvf textfile.tar.gz textfile  // Create tarball

Basic Networking Commands

ping 192.168.0.1
ping -c4 192.168.0.1 //  Send 4 packets only
ping -c4 192.168.0.1 -q //  Quiet mode
ping -c4 192.168.0.1 -v //  Verbose mode


ifconfig  //  Config of interfaces on machine
ifup  //  Brings an interface up
ifdown  //  Bring interface down

vim /etc/network/interfaces  //  Where interfaces are defined

ifconfig {nameofinterface} {ip} netmask {netmaskip}  //  Assign a netmask to specific device and interface  

netstat  //  Network connections open on machine
netstat -r  //  Kernel routing tables

rlogin  //  Remote login (replaced by ssh)

Emmet

Basics

div>ul>li

<div>
    <ul>
        <li></li>
    </ul>
</div>
div+p+bq

<div></div>
<p></p>
<blockquote></blockquote>
div+div>p>span+em 

<div></div>
<div>
    <p><span></span><em></em></p>
</div>
div+div>p>span+em^bq

<div></div>
<div>
    <p><span></span><em></em></p>
    <blockquote></blockquote>
</div>
div+div>p>span+em^^^bq

<div></div>
<div>
    <p><span></span><em></em></p>
</div>
<blockquote></blockquote>

Multiplication and grouping

ul>li*5
...outputs to

<ul>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
</ul>
div>(header>ul>li*2>a)+footer>p
...expands to

<div>
    <header>
        <ul>
            <li><a href=""></a></li>
            <li><a href=""></a></li>
        </ul>
    </header>
    <footer>
        <p></p>
    </footer>
</div>
(div>dl>(dt+dd)*3)+footer>p
...produces

<div>
    <dl>
        <dt></dt>
        <dd></dd>
        <dt></dt>
        <dd></dd>
        <dt></dt>
        <dd></dd>
    </dl>
</div>
<footer>
    <p></p>
</footer>
div#header+div.page+div#footer.class1.class2.class3
...will output

<div id="header"></div>
<div class="page"></div>
<div id="footer" class="class1 class2 class3"></div>
td[title="Hello world!" colspan=3]
...outputs

<td title="Hello world!" colspan="3"></td>
ul>li.item$*5
...outputs to

<ul>
    <li class="item1"></li>
    <li class="item2"></li>
    <li class="item3"></li>
    <li class="item4"></li>
    <li class="item5"></li>
</ul>

Attributes

ul>li.item$$$*5
...outputs to

<ul>
    <li class="item001"></li>
    <li class="item002"></li>
    <li class="item003"></li>
    <li class="item004"></li>
    <li class="item005"></li>
</ul>
ul>li.item$@-*5
…outputs to

<ul>
    <li class="item5"></li>
    <li class="item4"></li>
    <li class="item3"></li>
    <li class="item2"></li>
    <li class="item1"></li>
</ul>
ul>li.item$@3*5
…transforms to

<ul>
    <li class="item3"></li>
    <li class="item4"></li>
    <li class="item5"></li>
    <li class="item6"></li>
    <li class="item7"></li>
</ul>
ul>li.item$@-3*5
…is transformed to

<ul>
    <li class="item7"></li>
    <li class="item6"></li>
    <li class="item5"></li>
    <li class="item4"></li>
    <li class="item3"></li>
</ul>

Text

<!-- a{click}+b{here} -->
<a href="">click</a><b>here</b>

<!-- a>{click}+b{here} -->
<a href="">click<b>here</b></a>

p>{Click }+a{here}+{ to continue}
<p>Click <a href="">here</a> to continue</p>

p{Click }+a{here}+{ to continue}
<p>Click </p>
<a href="">here</a> to continue

Artisan Commands

Laracasts Commands


//  Quickly make a migration (but it misses unsigned on user_id)
php artisan make:migration:schema create_posts_table 
--schema="user_id:integer:foreign, title:string, body:text"

art make:migration:schema create_activities_table --schema="subject_id:integer:index, subject_type:string:index, name:string, user_id:integer:index"

// Quickly make a seeder
php artisan make:seed posts

JQuery Basics

Random JQuery reminders for noobs.

Remember that DOM must finish loading before JS interaction. Do that by waiting on ready:

jQuery(document).ready(function() {
   // Some code here.
});

Basics:

jQuery(document).ready(function() {
    $("h1");
    $("h1").text("New Heading");
    $("p > span");
    $("p > span").text();
    $("p > span").text('100');
    $("p").text("new text for paragraph");
});

Finding elements in the DOM.

//  Select via ID
$("#destinations");

//  Select via ID and descendant
$("#destinations li");
//  Via child
$("#destinations > li");

//  Select via Class
$(".destinations");

// Select via descendant
$( "form input" ).css( "border", "2px dotted blue" );
$( "form fieldset input" ).css( "backgroundColor", "yellow" );

// Multiple selectors
$(".destinations, .sale");

});

More advanced selectors

jQuery(document).ready(function() {
    $("li").text("Changes all nodes text values");
    $("li:first").text("Changes the first");
    $("li:last").text("Changes the last");
    $("li:even").text("Changes every second");
    $("#tours li:even").text("Changes every secondunder tours");
});

Traversing around the DOM

Selection > traversal
Walking the DOM

jQuery(document).ready(function() {
    $("li").first("Changes all nodes text values");
    $("li").first().next().text("Changes the second");
    $("li").last().prev().text("Changes the second");

    // Gets the parent (<ul>)
    $("li").first().parent();  

    // Gets the children, only the li
    $("#destinations").children("li");  

});

More Method Chaining

(function(){
    $.subscribe('form.submitted'), function() {
        $.('.flash').fadeIn(500).delay(1000).fadeOut(500);
    });
})();

Collections

Collections are extremely powerful.  Arrays on steroids

In a view, filter a collection based on a variable:


@foreach($notices->where('content_removed', 0, false) as $notice)

.....
@endforeach

Check if a collection has a record matching a primary key
$roles = User::find(1)->roles;
if ($roles->contains(2))
{
 //
}

Return as Array or String

$roles = User::find(1)->roles->toArray();

$roles = User::find(1)->roles->toJson();

Helper methods for looping and filtering

$roles = $user->roles->each(function($role)
{
 //
});

$users = $users->filter(function($user)
{
 return $user->isAdmin();
});

//  Apply callbacks to a loop
$roles = User::find(1)->roles;
$roles->each(function($role)
{
 //
});

Sorting collections

$roles = $roles->sortBy(function($role)
{
 return $role->created_at;
});

$roles = $roles->sortBy('created_at');

Bootstrap

Bootstrap 3.0 Usage

Tables

<table class="table table-striped table-bordered">
 <thead>
 <tr>
 <th class="col-md-4">Title</th>
 <th class="col-md-4">Title</th>
 <th class="col-md-4">Title</th>
 </tr>
 </thead>
 <tbody>
 @foreach($notices as $notice)
 <tr>
 <td>{{ $notice->provider_id }}</td>
 <td>{{ $notice->infringing_title }}</td>
 <td>{!! link_to($notice->infringing_link) !!}</td>
 </tr>
 @endforeach
 </tbody>
</table>

 

Input, Request & Validation

Input
Requests and Response
Validation
Files

Input

Input::get('key');
Input::get('key', 'default');
Input::has('key');
Input::all();
Input::only('foo', 'bar');
Input::except('foo');
Input::flush();

Session Input (flash)
Input::flash();
Input::flashOnly('foo', 'bar');
Input::flashExcept('foo', 'baz');
Input::old('key','default_value');

Files
Input::file('filename');
Input::hasFile('filename');
Input::file('name')->getRealPath();
Input::file('name')->getClientOriginalName();
Input::file('name')->getClientOriginalExtension();
Input::file('name')->getSize();
Input::file('name')->getMimeType();
Input::file('name')->move($destinationPath);
Input::file('name')->move($destinationPath, $fileName);

Request and Response

Request::url();
 Request::path();
 Request::getRequestUri();
 Request::getClientIp();
 Request::getUri();
 Request::getQueryString();
 Request::getPort();
 Request::is('foo/*');
 Request::segment(1);
 Request::header('Content-Type');
 Request::server('PATH_INFO');
 Request::ajax();
 Request::secure();
 Request::method();
 Request::isMethod('post');
 Request::instance()->getContent();
 Request::format();
 Request::isJson();
 Request::wantsJson();

Responses
return Response::make($contents);
return Response::make($contents, 200);
return Response::json(array('key' => 'value'));
return Response::json(array('key' => 'value'))
 ->setCallback(Input::get('callback'));
return Response::download($filepath);
return Response::download($filepath, $filename, $headers);
$response = Response::make($contents, 200);
$response->header('Content-Type', 'application/json');
return $response;
 return Response::make($content)
 ->withCookie(Cookie::make('key', 'value'));

Validation

Validator::make(
array('key' => 'Foo'),
array('key' => 'required|in:Foo')
);
Validator::extend('foo', function($attribute, $value, $params){});
Validator::extend('foo', 'FooValidator@validate');
Validator::resolver(function($translator, $data, $rules, $msgs)
{
return new FooValidator($translator, $data, $rules, $msgs);
});

Rules
accepted
active_url
after:YYYY-MM-DD
before:YYYY-MM-DD
alpha
alpha_dash
alpha_num
array
between:1,10
confirmed
date
date_format:YYYY-MM-DD
different:fieldname
digits:value
digits_between:min,max
boolean
email
exists:table,column
image
in:foo,bar,...
not_in:foo,bar,...
integer
numeric
ip
max:value
min:value
mimes:jpeg,png
regex:[0-9]
required
required_if:field,value
required_with:foo,bar,...
required_with_all:foo,bar,...
required_without:foo,bar,...
required_without_all:foo,bar,...
same:field
size:value
timezone
unique:table,column,except,idColumn
url

Files

File::exists('path');
File::get('path');
File::getRemote('path');
 File::getRequire('path');
 File::requireOnce('path');
 File::put('path', 'contents');
 File::append('path', 'data');
 File::delete('path');
 File::move('path', 'target');
 File::copy('path', 'target');
 File::extension('path');
 File::type('path');
 File::size('path');
 File::lastModified('path');
 File::isDirectory('directory');
 File::isWritable('path');
 File::isFile('file');
 File::glob($patterns, $flag);
 File::files('directory');
 File::allFiles('directory');
 File::directories('directory');
 File::makeDirectory('path', $mode = 0777, $recursive = false);
 File::copyDirectory('directory', 'destination', $options = null);
 File::deleteDirectory('directory', $preserve = false);
 File::cleanDirectory('directory');