tag:blogger.com,1999:blog-65344064014248410872024-02-19T16:13:47.445+08:00PHPerAnonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.comBlogger65125tag:blogger.com,1999:blog-6534406401424841087.post-20012836749122519942016-06-06T01:22:00.003+08:002016-06-06T10:46:31.363+08:00php版 取得台灣地址區碼<div class="markdown">
常常為了地址的事情感到麻煩,所以寫了一個程式能把舊5都地址轉新5都地址,再取得區碼的程式
[packagist.org](https://packagist.org/packages/recca0120/twzipcode)
[github](https://github.com/recca0120/twzipcode)
```bash
composer require recca0120/twzipcode
```
```php
use Recca0120\Twzipcode\Twzipcode;
$twzipcode = new Twzipcode('北 縣 萬里鄉中正路100號');
$twzipcode->getZipcode(); // 207
$twzipcode->getCounty(); // 新北市
$twzipcode->getDistrict(); // 萬里區
$twzipcode->getAddress(); // 新北市萬里區中正路100號
$twzipcode->getShortAddress(); // 中正路100號
```
</div>Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-16978819794550204442016-06-05T14:55:00.000+08:002016-06-05T15:15:05.392+08:00Laravel Repository<div class="markdown">
最近寫好的repository的package
還沒時間整理readme
所以就先拿phpunit來充當readme
[packagist.org](https://packagist.org/packages/recca0120/repository)
[github](https://github.com/recca0120/laravel-repository)
# Laravel Repository
[![Latest Stable Version](https://poser.pugx.org/recca0120/repository/v/stable)](https://packagist.org/packages/recca0120/repository)
[![Total Downloads](https://poser.pugx.org/recca0120/repository/downloads)](https://packagist.org/packages/recca0120/repository)
[![Latest Unstable Version](https://poser.pugx.org/recca0120/repository/v/unstable)](https://packagist.org/packages/recca0120/repository)
[![License](https://poser.pugx.org/recca0120/repository/license)](https://packagist.org/packages/recca0120/repository)
[![Monthly Downloads](https://poser.pugx.org/recca0120/repository/d/monthly)](https://packagist.org/packages/recca0120/repository)
[![Daily Downloads](https://poser.pugx.org/recca0120/repository/d/daily)](https://packagist.org/packages/recca0120/repository)
### Demo in tests/RepositoryTest.php
```php
use Faker\Factory as FakerFactory;
use Illuminate\Database\Eloquent\Model;
use Mockery as m;
use Recca0120\Repository\Criteria;
use Recca0120\Repository\EloquentRepository;
class EloquentRepositoryTest extends PHPUnit_Framework_TestCase
{
use Laravel;
public function setUp()
{
$app = $this->createApplication();
$db = $this->createDatabase();
Schema::create('users', function ($table) {
$table->increments('id');
$table->string('name');
$table->string('email');
$table->string('password', 60);
$table->rememberToken();
$table->timestamps();
});
Schema::create('roles', function ($table) {
$table->increments('id');
$table->string('name');
$table->string('description');
$table->timestamps();
});
Schema::create('user_roles', function ($table) {
$table->integer('user_id');
$table->integer('role_id');
});
$faker = FakerFactory::create();
for ($i = 0; $i < 3; $i++) {
User::create([
'name' => sprintf('%03d', $i + 1),
'email' => sprintf('%03d@test.com', $i + 1),
'password' => $faker->text,
]);
}
Role::create([
'name' => 'superuser',
'description' => 'superuser',
]);
Role::create([
'name' => 'administrator',
'description' => 'administrator',
]);
User::find(1)->roles()->sync([1]);
}
public function tearDown()
{
m::close();
Schema::drop('users');
}
public function test_repository_create()
{
$repository = new EloquentRepository(new User());
$repositoryUser = $repository->create([
'name' => 'test9999',
'email' => 'test9999@test.com',
'password' => str_random(30),
]);
$modelUser = User::where('name', '=', 'test9999')->first();
$this->assertSame($repositoryUser->id, $modelUser->id);
}
public function test_repository_find()
{
$repository = new EloquentRepository(new User());
$repositoryUser = $repository->find(1);
$modelUser = User::find(1);
$this->assertSame($repositoryUser->id, $modelUser->id);
}
public function test_repository_update()
{
$repository = new EloquentRepository(new User());
$repositoryUser = $repository->update([
'password' => 'test_update',
], 2);
$modelUser = User::find(2);
$this->assertSame($repositoryUser->id, $modelUser->id);
$this->assertSame($modelUser->password, 'test_update');
}
public function test_repository_delete()
{
$counter = User::count();
$repository = new EloquentRepository(new User());
$this->assertTrue($repository->delete(1));
$this->assertSame(User::count(), $counter - 1);
}
public function test_repository_find_all()
{
$repository = new EloquentRepository(new User());
$repositoryUsers = $repository->findAll();
$modelUsers = User::all();
$this->assertSame($repositoryUsers->toArray(), $modelUsers->toArray());
}
public function test_find_by_criteria()
{
$repository = new EloquentRepository(new User());
$criteria = (new Criteria())
->where('name', '0001')
->having('email', '=', '0001@test.com')
->groupBy('name');
$repositoryUsers = $repository->findBy($criteria);
$modelUsers = User::where('name', 'like', '0001')
->where('email', '0001@test.com')
->groupBy('name')
->get();
$this->assertSame($repositoryUsers->toArray(), $modelUsers->toArray());
}
public function test_find_by_criteria_where()
{
$repository = new EloquentRepository(new User());
$criteria = (new Criteria())
->where('name', '0001');
$repositoryUsers = $repository->findBy($criteria);
$modelUsers = User::where('name', '0001')
->get();
$this->assertSame($repositoryUsers->toArray(), $modelUsers->toArray());
}
public function test_find_by_criteria_where_closure()
{
$repository = new EloquentRepository(new User());
$criteria = (new Criteria())
->where(function ($criteria) {
return $criteria->where('name', '0001');
});
$repositoryUsers = $repository->findBy($criteria);
$modelUsers = User::where(function ($query) {
return $query->where('name', '0001');
})->get();
$this->assertSame($repositoryUsers->toArray(), $modelUsers->toArray());
}
public function test_find_by_criteria_or_where()
{
$repository = new EloquentRepository(new User());
$criteria = (new Criteria())
->where('name', '0001')
->orWhere('name', '0002');
$repositoryUsers = $repository->findBy($criteria);
$modelUsers = User::where('name', '0001')
->orWhere('name', '0002')
->get();
$this->assertSame($repositoryUsers->toArray(), $modelUsers->toArray());
}
public function test_find_by_criteria_or_where_closure()
{
$repository = new EloquentRepository(new User());
$criteria = (new Criteria())
->where(function ($criteria) {
return $criteria->where('name', '0001')
->orWhere('name', '0002');
});
$repositoryUsers = $repository->findBy($criteria);
$modelUsers = User::where(function ($query) {
return $query->where('name', '0001')
->orWhere('name', '0002');
})->get();
$this->assertSame($repositoryUsers->toArray(), $modelUsers->toArray());
}
public function test_criteria_where_has()
{
$repository = new EloquentRepository(new User());
$criteria = (new Criteria())
->whereHas('roles', function ($criteria) {
return $criteria->where('id', '=', 1);
});
$repositoryUsers = $repository->findBy($criteria);
$modelUsers = User::whereHas('roles', function ($query) {
return $query->where('id', '=', 1);
})
->get();
$this->assertSame($repositoryUsers->toArray(), $modelUsers->toArray());
}
public function test_criteria_join()
{
$repository = new EloquentRepository(new User());
$criteria = (new Criteria())
->join('user_roles', function ($criteria) {
return $criteria->on('users.id', '=', 'user_roles.user_id');
});
$repositoryUsers = $repository->findBy($criteria);
$modelUsers = User::join('user_roles', function ($query) {
return $query->on('users.id', '=', 'user_roles.user_id');
})
->get();
$this->assertSame($repositoryUsers->toArray(), $modelUsers->toArray());
}
public function test_criteria_order_by()
{
$repository = new EloquentRepository(new User());
$criteria = (new Criteria())
->orderBy('name', 'desc');
$repositoryUsers = $repository->findBy($criteria);
$modelUsers = User::orderBy('name', 'desc')
->get();
$this->assertSame($repositoryUsers->toArray(), $modelUsers->toArray());
}
public function test_criteria_select()
{
$repository = new EloquentRepository(new User());
$criteria = (new Criteria())
->select('name');
$repositoryUsers = $repository->findBy($criteria);
$modelUsers = User::select('name')
->get();
$this->assertSame($repositoryUsers->toArray(), $modelUsers->toArray());
}
public function test_criteria_experssion()
{
$repository = new EloquentRepository(new User());
$criteria = (new Criteria())
->select(Criteria::expr('REPLACE(name, "0001", "0003")'));
$repositoryUsers = $repository->findBy($criteria);
$modelUsers = User::select(DB::raw('REPLACE(name, "0001", "0003")'))
->get();
$this->assertSame($repositoryUsers->toArray(), $modelUsers->toArray());
}
public function test_criteria_paginated()
{
$repository = new EloquentRepository(new User());
$repositoryUsers = $repository->paginatedAll(15);
$modelUsers = User::paginate(15);
$this->assertSame($repositoryUsers->toArray(), $modelUsers->toArray());
}
public function test_criteria_with()
{
$repository = new EloquentRepository(new User());
$criteria = (new Criteria())
->with('roles');
$repositoryUsers = $repository->findBy($criteria);
$modelUsers = User::with('roles')->get();
$this->assertSame($repositoryUsers->toArray(), $modelUsers->toArray());
}
public function test_find_by_array()
{
$repository = new EloquentRepository(new User());
$repositoryUsers = $repository->findBy([
['name', '=', '0002'],
['email', '=', '0002@test.com'],
]);
$modelUsers = User::where('name', '0002')
->where('email', '0002@test.com')->get();
$this->assertSame($repositoryUsers->toArray(), $modelUsers->toArray());
}
public function test_find_by_array_key()
{
$repository = new EloquentRepository(new User());
$repositoryUsers = $repository->findBy([
'name' => '0002',
'email' => '0002@test.com',
]);
$modelUsers = User::where('name', '0002')
->where('email', '0002@test.com')->get();
$this->assertSame($repositoryUsers->toArray(), $modelUsers->toArray());
}
public function test_custom_criteria()
{
$repository = new EloquentRepository(new User());
$repositoryUsers = $repository->findBy(new CustomCriteria());
$modelUsers = User::where('name', '0002')->get();
$this->assertSame($repositoryUsers->toArray(), $modelUsers->toArray());
}
public function test_multiple_criteria()
{
$repository = new EloquentRepository(new User());
$repositoryUsers = $repository->findBy([
new CustomCriteria(),
(new Criteria())->orderBy('name', 'desc'),
]);
$modelUsers = User::where('name', '0002')
->orderBy('name', 'desc')->get();
$this->assertSame($repositoryUsers->toArray(), $modelUsers->toArray());
}
}
class CustomCriteria extends Criteria
{
public function __construct()
{
$this->where('name', '0002');
}
}
class User extends Model
{
protected $fillable = [
'name', 'email', 'password',
];
public function roles()
{
return $this->belongsToMany(
Role::class,
'user_roles',
'role_id',
'user_id'
);
}
}
class Role extends Model
{
protected $fillable = [
'name', 'description',
];
public function users()
{
return $this->belongsToMany(
self::class,
'user_roles',
'user_id',
'role_id'
);
}
}
function dump()
{
call_user_func_array('var_dump', func_get_args());
}
```
</div>Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-78673761877358085652016-06-05T14:53:00.001+08:002016-06-05T15:14:09.702+08:00Laravel Terminal<div class="markdown">
這是一個將artisan移植到web介面的package,
並增加了一些自定義的command
在server不支援bash shell時,還能執行一些aritsan的命令
[packagist.org](https://packagist.org/packages/recca0120/terminal)
[github](https://github.com/recca0120/laravel-terminal)
# Laravel Web Artisan
[![Latest Stable Version](https://poser.pugx.org/recca0120/terminal/v/stable)](https://packagist.org/packages/recca0120/terminal)
[![Total Downloads](https://poser.pugx.org/recca0120/terminal/downloads)](https://packagist.org/packages/recca0120/terminal)
[![Latest Unstable Version](https://poser.pugx.org/recca0120/terminal/v/unstable)](https://packagist.org/packages/recca0120/terminal)
[![License](https://poser.pugx.org/recca0120/terminal/license)](https://packagist.org/packages/recca0120/terminal)
[![Monthly Downloads](https://poser.pugx.org/recca0120/terminal/d/monthly)](https://packagist.org/packages/recca0120/terminal)
[![Daily Downloads](https://poser.pugx.org/recca0120/terminal/d/daily)](https://packagist.org/packages/recca0120/terminal)
## Installation
Add Presenter to your composer.json file:
```js
"require": {
"recca0120/terminal": "^1.3.3"
}
```
Now, run a composer update on the command line from the root of your project:
```
composer update
```
### Registering the Package
Include the service provider within `app/config/app.php`. The service povider is needed for the generator artisan command.
```php
'providers' => [
...
Recca0120\Terminal\ServiceProvider::class,
...
];
```
publish
```php
artisan vendor:publish --provider="Recca0120\Terminal\ServiceProvider"
```
### URL
http://localhost/path/to/terminal
### Whitelist
```php
return [
'whitelists' => ['127.0.0.1', 'your ip'],
];
```
## Available Commands
* artisan
* artisan tinker
* find
* mysql
### Find
not full support, but you can delete file use this function (please check file permission)
```bash
find ./vendor -name tests -type d -maxdepth 4 -delete
```
## Add Your Command
### Add Command Class
```php
// src/Console/Commands/Mysql.php
namespace Recca0120\Terminal\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Foundation\Inspiring;
class Inspire extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'inspire';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Display an inspiring quote';
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->comment(PHP_EOL.Inspiring::quote().PHP_EOL);
}
}
```
### Add Command
```php
// src/Console/Kernel.php
namespace Recca0120\Terminal\Console;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use Recca0120\Terminal\Console\Application as Artisan;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
Commands\Inspire::class,
];
}
```
## ScreenShot
### Available Commands
```bash
$ help
```
![Available Commands](https://cdn.rawgit.com/recca0120/terminal/master/screenshots/available-commands.png)
### Artisan List
```bash
$ artisan
```
![Artisan List](https://cdn.rawgit.com/recca0120/terminal/master/screenshots/artisan-list.png)
### Migrate
```bash
$ artisan migrate --seed
```
![Migrate](https://cdn.rawgit.com/recca0120/terminal/master/screenshots/artisan-migrate.png)
### Artisan Tinker
```bash
$ artisan tinker
```
![Tinker](https://cdn.rawgit.com/recca0120/terminal/master/screenshots/artisan-tinker.png)
### Find Command
```bash
$ find ./ -name * -maxdepth 1
```
![Find Command](https://cdn.rawgit.com/recca0120/terminal/master/screenshots/find-command.png)
### Find and Delete
```bash
$ find ./storage/logs -name * -maxdepth 1 -delete
```
![Find and Delete](https://cdn.rawgit.com/recca0120/terminal/master/screenshots/find-and-delete.png)
### Vi
```bash
$ vi server.php
```
![Vi Command](https://cdn.rawgit.com/recca0120/terminal/master/screenshots/vi-command.png)
![Vi Editor](https://cdn.rawgit.com/recca0120/terminal/master/screenshots/vi-editor.png)
![Vi Save](https://cdn.rawgit.com/recca0120/terminal/master/screenshots/vi-save.png)
### Tail
```bash
$ tail
$ tail --line=1
$ tail server.php
$ tail server.php --line 5
```
![Tail Command](https://cdn.rawgit.com/recca0120/terminal/master/screenshots/tail-command.png)
### Cleanup
```bash
$ cleanup
```
![Cleanup Command](https://cdn.rawgit.com/recca0120/terminal/master/screenshots/cleanup-command.png)
</div>Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-67756898282706454712016-06-05T14:52:00.000+08:002016-06-05T15:13:09.024+08:00Laravel Tracy<div class="markdown">
一個laravel的debug工具,它是MIT的!大家可以安裝來試看看
用得習慣的話就請多多使用....
[packagist.org](https://packagist.org/packages/recca0120/laravel-tracy)
[github](https://github.com/recca0120/laravel-tracy)
## [Nette Tracy](https://github.com/nette/tracy.git) for Laravel 5
Better Laravel Exception Handler
[![Latest Stable Version](https://poser.pugx.org/recca0120/laravel-tracy/v/stable)](https://packagist.org/packages/recca0120/laravel-tracy)
[![Total Downloads](https://poser.pugx.org/recca0120/laravel-tracy/downloads)](https://packagist.org/packages/recca0120/laravel-tracy)
[![Latest Unstable Version](https://poser.pugx.org/recca0120/laravel-tracy/v/unstable)](https://packagist.org/packages/recca0120/laravel-tracy)
[![License](https://poser.pugx.org/recca0120/laravel-tracy/license)](https://packagist.org/packages/recca0120/laravel-tracy)
[![Monthly Downloads](https://poser.pugx.org/recca0120/laravel-tracy/d/monthly)](https://packagist.org/packages/recca0120/laravel-tracy)
[![Daily Downloads](https://poser.pugx.org/recca0120/laravel-tracy/d/daily)](https://packagist.org/packages/recca0120/laravel-tracy)
<img src="https://cdn.rawgit.com/recca0120/laravel-tracy/master/screenshots/tracy.png" width="100%" />
## Features
- Visualization of errors and exceptions
- Debugger Bar
- Exception stack trace contains values of all method arguments.
## Online Demo
[Demo](https://cdn.rawgit.com/recca0120/laravel-tracy/master/screenshots/tracy-exception.html)
## Installing
To get the latest version of Laravel Exceptions, simply require the project using [Composer](https://getcomposer.org):
```bash
composer require recca0120/laravel-tracy
```
Instead, you may of course manually update your require block and run `composer update` if you so choose:
```json
{
"require": {
"recca0120/laravel-tracy": "~1.3.5"
}
}
```
Include the service provider within `config/app.php`. The service povider is needed for the generator artisan command.
```php
'providers' => [
...
Recca0120\LaravelTracy\ServiceProvider::class,
...
];
```
publish
```bash
artisan vendor:publish --provider="Recca0120\LaravelTracy\ServiceProvider"
```
## Config
```php
return [
'ajax' => [
'debugbar' => false, // enable render debugbar when http request is ajax
'gzCompressLevel' => 5, // gzcompress level
/*
* http://stackoverflow.com/questions/3326210/can-http-headers-be-too-big-for-browsers/3431476#3431476
* Lowest limit found in popular browsers:
* - 10KB per header
* - 256 KB for all headers in one response.
* - Test results from MacBook running Mac OS X 10.6.4:
*/
'maxHeaderSize' => 102400, // 102400b its => 100 kb
],
'basePath' => null,
'strictMode' => true,
'maxDepth' => 4,
'maxLen' => 1000,
'showLocation' => true,
'editor' => 'subl://open?url=file://%file&line=%line',
'panels' => [
'routing' => true,
'database' => true,
'view' => true,
'session' => true,
'request' => true,
'event' => false,
'user' => true,
'terminal' => true,
],
// value: js or tracy
'panelDumpMethod' => 'js', // tracy dump need more memory
];
```
### Editor Link
windows
```
copy <vendor path>/recca0120/laravel-tracy/tools/subl-handler/subl-handler.vbs to any directory where you want to place
double click subl-handler.vbs and select editor (support eclipse, sublime, notepad++, else...)
```
OSX
```
https://github.com/dhoulb/subl
```
## Debugger Bar
### SystemInfo
![SystemInfo](https://cdn.rawgit.com/recca0120/laravel-tracy/master/screenshots/systeminfo.png)
### Route
![Route](https://cdn.rawgit.com/recca0120/laravel-tracy/master/screenshots/route.png)
### View
![View](https://cdn.rawgit.com/recca0120/laravel-tracy/master/screenshots/view.png)
### Session
![Session](https://cdn.rawgit.com/recca0120/laravel-tracy/master/screenshots/session.png)
### Request
![Request](https://cdn.rawgit.com/recca0120/laravel-tracy/master/screenshots/request.png)
### Login
![Login](https://cdn.rawgit.com/recca0120/laravel-tracy/master/screenshots/login.png)
### Web Artisan
web artisan is another package [recca0120/terminal](https://github.com/recca0120/laravel-terminal)
![Terminal](https://cdn.rawgit.com/recca0120/laravel-tracy/master/screenshots/terminal.png)
#### notice
if you install terminal before, this panel will throw errors, please remove folder `app/resources/views/vendor/terminal`
## ISSUE
when ajax debugbar is enabled and debugbar is bigger than 256k, will throw 500 exception, or browser will be no response
so I try to compress debugbar in php, and decompress debugbar in javascript.
It looks like working at chrome 48.0.2564.116 64bit, windows 10
but if you use Laravel-Tracy and it doesn't work correctly
you can try
- disable panel [view , request, event]
- panelDumpMethod change to js
- disable ajax debugbar
</div>Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-27343140439439059202016-05-12T15:13:00.002+08:002016-05-12T17:23:54.009+08:00活用 es6 generator + co 讓async看起來像sync<div class="markdown">
仔細研究了es6的generator function + [co](https://github.com/tj/co "co")
才發現可以利用它來改善我們的程式寫法
讓程式的可讀性更高
先讓我們看看用Promise來撰寫非同步code的樣子
```javascript
let num = function (num) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(num+1);
}, 500);
});
}
num(1).then((res) => {
return num(res);
}).then((res) => {
return num(res);
}).then((res) => {
// output
// promise result: 4
console.log(`promise result: ${res}`);
});
```
接下來讓我們來看看generator function + [co](https://github.com/tj/co "co")的寫法
```javascript
let num = function (num) {
return (callback) => {
setTimeout(function() {
callback(null, num+1);
}, 500);
}
}
co(function*() {
let num1 = yield num(1);
let num2 = yield num(num1);
let num3 = yield num(num2);
return num3;
}).then((res) => {
// output
// generator result: 4
console.log(`generator result: ${res}`);
});
```
[jsfiddle](https://jsfiddle.net/recca0120/eocp5h2c/ "jsfiddle範例")
</div>Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-58010372729625723382016-04-25T04:18:00.000+08:002016-04-25T04:18:54.049+08:00ubuntu下安裝atom editor<div class="markdown">
只要執行三行指令即可
```bash
sudo add-apt-repository ppa:webupd8team/atom
sudo apt-get update
sudo apt-get install atom
```
</div>Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-36667077782995977612016-04-25T01:48:00.000+08:002016-04-25T09:20:33.964+08:00Linux使用php7連接mssql,並設定utf-8<div class="markdown">
使用php7要連接mssql要安裝的套件為pdo_dblib
```bash
# centos
yum install php70w-pdo_dblib.x86_64
# ubuntu
sudo apt-get install freetds-bin php-sybase
```
接下來我們更改freetds的設定檔,裝連線設定為utf8
```bash
# centos
vi /etc/freetds.conf
# ubuntu
sudo vi /etc/freetds/freetds.conf
```
加入兩行設定即可
```ini
# centos
tds version = 7.2
client charset = UTF-8
# ubuntu
tds version = 7.1
client charset = UTF-8
```
![freetds config](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfZxvhvTwGAuP2pwtB80Bbypwb54mp8uAIPe5kAPEB8Swk4l5BFpt0ZncIr_SMZ43RW5ibnF7SOP_AeE5D7PX5JFbk2uBPZkK_Q0jL0MFFlMXRkmgJeUNFv17CszpfALpdfu-HJ23aKN92/s1600/Image+3.png)
設定完成後連線到mssql charset就會是utf8
如果還是顯示為亂碼的話則可以利用tsql的指令來debug
```bash
tsql -S [ip] -U [username] -P [password]
```
![tsql](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhplyPJmyyXaqfmXpo1D9Tl72GhIOrn_P2QgjwASD3-QNn_3YUyVBsCX6FPv0TdYC6D9hhYd2JIVR8OEHZXnBErLy2004Kmsah5y1YOqCoZ5WtiPL5sbYzWiB-6dxaPz3OKny6Ji2qJw-Vf/s1600/Image+2.png)
</div>
<!--
補充說明:
要能支援utf8有幾個必要條件
- 必須為mssql 2008以上
- 欄位必須指定為nchar或nvarchar
[參考http://stackoverflow.com/questions/12512687/sql-server-utf8-howto](http://stackoverflow.com/questions/12512687/sql-server-utf8-howto)
SET ANSI_NULLS ON;
SET ANSI_WARNINGS ON;
GO
-->Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-51079318438638585872016-04-03T19:55:00.000+08:002016-04-03T19:55:00.970+08:00es6如何拓增prototype<div class="markdown">
寫es6時要增加Object的prototype
已經和以往的寫法大為不同了
所以就來介紹一下方法吧
```js
// $.inArray 模擬 Array.includes
import $ from 'jquery';
if (!Array.prototype.includes) {
Object.defineProperty(Array.prototype, 'includes', {
value(...args) {
return $.inArray(...args, this) !== -1;
}
});
}
```
</div>Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-49778484387142602142016-04-03T19:50:00.002+08:002016-04-03T19:55:45.554+08:00利用jQuery Promise模擬Native Promise<div class="markdown">
我們在寫es6時,會用到一些es6才有的函式或物件
但如果可以使用jQuery的一些內建函式來模擬的話
我們就不需要import 'babel-polyfill'
這樣產出來的javascript檔案就會少個90k左右
以下為程式碼
```js
'use strict';
import $ from 'jquery';
if (!window.Promise) {
class Promise {
constructor(callback) {
this.deferred = $.Deferred();
callback((o) => {
this.deferred.resolve(o);
}, (o) => {
this.deferred.reject(o);
});
this.promise = this.deferred.promise();
}
then(resolve, reject) {
this.promise.done(resolve);
this.promise.fail(reject);
return this;
}
catch(reject) {
this.promise.fail(reject);
return this;
}
}
window.Promise = Promise;
}
```
</div>Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-24871808869506960892016-04-03T19:39:00.001+08:002016-04-03T19:58:32.550+08:00解決babel6 class extends 在 ie10 以下版本super無法呼叫 parent constructor<div class="markdown">
先直接看程式碼
```js
class A {
constructor() {
console.log('A');
}
}
class B extends A {
constructor() {
super();
}
}
new B();
```
這是一個很簡單物件繼承,預期console內輸出 "A"
實際做了測試之後發現在ie11, chrome, firefox都能正常輸出
但在ie9, ie10卻完全失效
後來查了原因後原來Object.getPrototypeOf在es5及es6的功能完全不同
才造成super失效
在github上已經有人提出兩種出解決方案
1.設定babel的plugins
```json
{
"presets": ["react", "es2015"],
"plugins": [
["transform-es2015-classes", { "loose": true }],
"transform-proto-to-assign"
]
}
```
2.修改Object.getPrototypeOf 來自[https://github.com/seznam/IMA.js-babel6-polyfill](https://github.com/seznam/IMA.js-babel6-polyfill "polyfill")
```js
(function() {
var testObject = {};
if (!(Object.setPrototypeOf || testObject.__proto__)) {
var nativeGetPrototypeOf = Object.getPrototypeOf;
Object.getPrototypeOf = function(object) {
if (object.__proto__) {
return object.__proto__;
} else {
return nativeGetPrototypeOf.call(Object, object);
}
}
}
})();
```
</div>Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-12318585798556024052016-03-13T21:46:00.003+08:002016-03-13T21:52:24.429+08:00php composite + __call<div class="markdown">
```php
class Weapon
{
protected $name;
protected $attack = 0;
protected $addions = [];
public function __construct($name, $attack, $addions = [])
{
$this->name = $name;
$this->attack = $attack;
$this->addions = $addions;
}
public function setAttack($attack)
{
$this->attack = $attack;
}
public function attack()
{
$attack = $this->attack;
foreach ($this->addions as $addion) {
$attack += $addion->attack();
}
return $attack;
}
public function __call($method, $parameters)
{
foreach ($this->addions as $addion) {
if (method_exists($addion, $method) === true) {
return call_user_func_array([$addion, $method], $parameters);
}
}
die('error');
}
}
abstract class Addion
{
protected $attack = 0;
public function attack()
{
return $this->attack;
}
}
class ToxicAddion extends Addion
{
protected $attack = 15;
public function toxic()
{
echo 'toxic';
}
}
class LightingAddion extends Addion
{
protected $attack = 10;
public function lighting()
{
echo 'lighting';
}
}
$sword = new Weapon('劍', 10, [
new ToxicAddion(),
new LightingAddion(),
]);
echo $sword->attack();
echo $sword->toxic();
echo $sword->lighting();
// output
// 35
// toxic
// lighting
```
</div>Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-90868885060962519142016-03-13T21:36:00.000+08:002016-03-13T21:47:57.652+08:00PHP decorator + __call<div class="markdown">
```
class Weapon
{
public function attack()
{
return 10;
}
}
abstract class Decorator
{
protected $weapon;
public function __construct($weapon)
{
$this->weapon = $weapon;
}
abstract public function attack();
public function __call($method, $parameters)
{
return call_user_func_array([$this->weapon, $method], $parameters);
}
}
class ToxicDecorator extends Decorator
{
public function attack()
{
return $this->weapon->attack() + 15;
}
public function toxic()
{
echo 'toxic';
}
}
class LightingDecorator extends Decorator
{
public function attack()
{
return $this->weapon->attack() + 5;
}
public function lighting()
{
echo 'lighting';
}
}
$weapon = new Weapon();
$weapon = new ToxicDecorator($weapon);
$weapon = new LightingDecorator($weapon);
echo $weapon->attack();
echo $weapon->toxic();
echo $weapon->lighting();
// output
// 30
// toxic
// lighting
```
</div>Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-90745680427782948462016-02-16T12:42:00.001+08:002016-02-16T12:45:45.539+08:00PHP 超簡易的樣版引擎<div class="markdown">
PHP的樣版引擎實在是多到不可數
而且每個樣版引擎的做法都不盡相同
有時何我們只需要一個很簡單的把php程式碼分離
就可以用這個最簡單的做法
test.php
```php
<?php foreach ($data as $v): ?>
<?php echo $v; ?>
<?php endforeach; ?>
```
view.php
```php
function view($file, $data)
{
ob_start();
extract($data);
require $file;
return ob_get_clean();
}
echo view('test.php', ['data' => [
1, 2, 3,
]]);
```
</div>Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-35667448275725166722016-02-16T12:11:00.002+08:002016-02-16T12:15:06.307+08:00獨立使用Laravel Blade Template Engine<div class="markdown">
有別於之前獨立使用Socialite
這次我們利用ServiceProvider來設定Laravel Blade Engine
利用composer安裝 illuminate/view
```
composer require illunimate/view
```
config.php
```php
require __DIR__.'/vendor/autoload.php';
use Illuminate\Container\Container;
use Illuminate\Events\Dispatcher;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Facades\Facade;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Fluent;
use Illuminate\View\ViewServiceProvider;
$app = new Container();
$app['events'] = new Dispatcher();
$app['config'] = new Fluent();
$app['files'] = new Filesystem();
// 設定view資料夾
$app['config']['view.paths'] = [__DIR__.'/views/'];
// 設定快取資料夾
$app['config']['view.compiled'] = __DIR__.'/compiled/';
// 利用ServiceProvider來初始化View
$serviceProvider = new ViewServiceProvider($app);
// 註冊
$serviceProvider->register();
// boot
$serviceProvider->boot();
Facade::setFacadeApplication($app);
// 設Facade View Alias方便使用
class_alias(View::class, 'View');
```
views/test.blade.php
```php
@foreach ([1,2,3] as $v)
{{ $v }}
@endforeach
```
index.php
```php
require __DIR__.'/config.php';
echo View::make('test')->render();
```
完整檔案在[Github](https://github.com/recca0120/laravel-blade-standalone-demo)
</div>Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-26264880872378345252016-02-04T01:07:00.003+08:002016-02-04T01:07:43.247+08:00Mock Laravel Application<div class="markdown">
研究了好久的mockery終於理出一些頭緒了
Laravel的Application的Mock原來如此簡單
```php
m::mock('Illuminate\Container\Container, Illuminate\Contracts\Foundation\Application')
->makePartial()
->shouldReceive('basePath')->andReturn(realpath(__DIR__.'/../').'/')
->shouldReceive('version')->andReturn('5.x.testing')
->shouldReceive('environment')->andReturn('testing')
->mock();
```
</div>Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-24303584025228409862016-02-01T05:33:00.001+08:002016-02-01T05:35:45.843+08:00獨立使用Laravel Socialite<div class="markdown">
有別於前一篇,這次我們用不使用Illuminate\Container\Container來執行Laravel Socialite
## composer
```
composer require laravel/socialite
```
## php
```php
require __DIR__.'/vendor/autoload.php';
use Illuminate\Http\Request;
use Illuminate\Support\Fluent;
use Laravel\Socialite\SocialiteManager;
use Symfony\Component\HttpFoundation\Session\Session;
/*
* 用 \Illuminate\Support\Fluent
* 替代 \Illuminate\Container\Container
*/
$app = new Fluent();
/*
* 用 \Illuminate\Support\Fluent
* 替代 \Illuminate\Contracts\Config\Repository
*/
$config = new Fluent();
/*
* 取得 Request
*/
$request = Request::capture();
/*
* 使用 Symfony Session
*/
$session = new Session();
/*
* session start
*/
$session->start();
/*
* 設置 session
*/
$request->setSession($session);
/*
* Facebook飍數
*/
$config['services.facebook'] = [
'client_id' => '900358040081723',
'client_secret' => '06134ad6946069c6457d06688b22c259',
'redirect' => 'http://localhost/test/socialite/index.php/callback',
];
/*
* 將 config, request置入 app
*/
$app['config'] = $config;
$app['request'] = $request;
// 以上為 socalite app所需設定,接下來參考官方文件即可
$socialiteManager = new SocialiteManager($app);
$provider = $socialiteManager
->with('facebook')
/*
* 只要是oauth2就必須執行此方法,
* 因為我們用的是Symfony Session而不是Laravel Session
*/
->stateless();
if (strpos($_SERVER['REQUEST_URI'], '/callback') === false) {
$response = $provider->redirect();
return $response->send();
}
var_dump((array) $provider->user());
```
</div>
Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-79461203045329829472016-01-31T02:19:00.002+08:002016-02-01T03:26:52.201+08:00如何獨立使用Laravel Eloquent<div class="markdown">
Laravel的套件是可以獨立使用的,並不需要加入整個framework
我們一起來了解如何操作
composer 新增套件
```bash
composer require illuminate/container illuminate/contracts illuminate/database illuminate/events illuminate/hashing illuminate/support nesbot/carbon
```
新增bootstrap.php
```php
require __DIR__.'/../vendor/autoload.php';
use Illuminate\Container\Container;
use Illuminate\Support\Facades\Facade;
use Illuminate\Support\Str;
class Application extends Container
{
public $aliases = [
\Illuminate\Support\Facades\Facade::class => 'Facade',
\Illuminate\Support\Facades\App::class => 'App',
\Illuminate\Support\Facades\Schema::class => 'Schema',
];
public function __construct()
{
date_default_timezone_set('UTC');
if (class_exists('\Carbon\Carbon') === true) {
\Carbon\Carbon::setTestNow(\Carbon\Carbon::now());
}
$this['app'] = $this;
$this->setupAliases();
$this->setupDispatcher();
$this->setupConnection();
Facade::setFacadeApplication($this);
Container::setInstance($this);
}
public function setupDispatcher()
{
if (class_exists('\Illuminate\Events\Dispatcher') === false) {
return;
}
$this['events'] = new \Illuminate\Events\Dispatcher($this);
}
public function setupAliases()
{
foreach ($this->aliases as $className => $alias) {
class_alias($className, $alias);
}
}
public function setupConnection()
{
if (class_exists('\Illuminate\Database\Capsule\Manager') === false) {
return;
}
$connection = new \Illuminate\Database\Capsule\Manager();
$connection->addConnection([
'driver' => 'sqlite',
'database' => ':memory:',
]);
if (isset($this['events']) === true) {
$connection->setEventDispatcher($this['events']);
}
$connection->bootEloquent();
$connection->setAsGlobal();
$this['db'] = $connection;
}
public function migrate($method)
{
if (class_exists('\Illuminate\Database\Capsule\Manager') === false) {
return;
}
foreach (glob(__DIR__.'/../database/migrations/*.php') as $file) {
include_once $file;
if (preg_match('/\d+_\d+_\d+_\d+_(.*)\.php/', $file, $m)) {
$className = Str::studly($m[1]);
$migration = new $className();
call_user_func_array([$migration, $method], []);
}
}
}
public function environment()
{
return 'testing';
}
}
if (function_exists('bcrypt') === false) {
/**
* Hash the given value.
*
* @param string $value
* @param array $options
*
* @return string
*/
function bcrypt($value, $options = [])
{
return (new \Illuminate\Hashing\BcryptHasher())->make($value, $options);
}
}
if (function_exists('app') === false) {
function app()
{
return App::getInstance();
}
}
if (Application::getInstance() == null) {
new Application();
}
```
只要再建立資料表及建立Model
就可以正常使用Eloquent了
</div>Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-45812229347083859572016-01-03T18:46:00.001+08:002016-01-03T18:46:49.005+08:00git 刪除遠端branch<div class="markdown">
只要在分支前加入『:』即可
##Example
```bash
git push origin :<branch name>
```
</div>Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-90367157114615230482015-12-28T19:28:00.000+08:002015-12-28T19:30:04.939+08:00遠振主機 escapeshellarg() has been disabled for security reasons<div class="markdown">
用遠振主機又踩雷啦,遠振將escapeshellarg這個函式disabled
所以只要有用到
SebastianBergmann\Environment\Runtime
Symfony\Component\Console\Input\Input
Symfony\Component\HttpFoundation\File\MimeType\FileBinaryMimeTypeGuesser
Symfony\Component\Process\ProcessUtils
Tracy\Debugger
都會提示 escapeshellarg() has been disabled for security reasons
不過還好php5.3之後就支援namespace,可以讓我們輕鬆略過這個問題
(如果使用的套件不支援namespace那就只好認命的去修改程式囉)
只要require下面的檔案就可以解決這些問題了
```php
namespace Yuan\Jhen
{
if (function_exists('escapeshellarg') === true) {
function escapeshellarg($input)
{
return \escapeshellarg($input);
}
} else {
function escapeshellarg($input)
{
$input = str_replace('\'', '\\\'', $input);
return '\''.$input.'\'';
}
}
}
namespace SebastianBergmann\Environment
{
function escapeshellarg($input)
{
return \Yuan\Jhen\escapeshellarg($input);
}
}
namespace Symfony\Component\Console\Input
{
function escapeshellarg($input)
{
return \Yuan\Jhen\escapeshellarg($input);
}
}
namespace Symfony\Component\HttpFoundation\File\MimeType
{
function escapeshellarg($input)
{
return \Yuan\Jhen\escapeshellarg($input);
}
}
namespace Symfony\Component\Process
{
function escapeshellarg($input)
{
return \Yuan\Jhen\escapeshellarg($input);
}
}
namespace Tracy
{
function escapeshellarg($input)
{
return \Yuan\Jhen\escapeshellarg($input);
}
}
```
</div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsakGzmlvmQo2kl-9j7y0GbneNx6kMPj7FUhdOlAS2Y9O0bzGG3GzsKJcZ3bWkVDN-9Z1vjiRVkSneBcl-P-60F7uoqE_R2lCaYHD6gZS2WZn1UgkTVgiQ2iYJV3B3cFt3KdEpQ-wajzXc/s1600/Image+1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsakGzmlvmQo2kl-9j7y0GbneNx6kMPj7FUhdOlAS2Y9O0bzGG3GzsKJcZ3bWkVDN-9Z1vjiRVkSneBcl-P-60F7uoqE_R2lCaYHD6gZS2WZn1UgkTVgiQ2iYJV3B3cFt3KdEpQ-wajzXc/s320/Image+1.png" /></a></div>Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-56027712103043747962015-12-22T04:07:00.001+08:002015-12-22T04:16:23.203+08:00利用Git來升級Laravel<div class="markdown">
照著影片操作,就會出現conflicts,處理完conflicts之後,再執行
```bash
composer install
```
這樣大致上就升級完畢了,而且如果升級出問題還可以利用git本身的功能來進行還原...
</div>
<div class="separator" style="clear: both; text-align: center;">
<iframe width="320" height="266" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/OtvAwl4Nspk/0.jpg" src="https://www.youtube.com/embed/OtvAwl4Nspk?feature=player_embedded" frameborder="0" allowfullscreen></iframe></div>
<br />Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-74694425722861693182015-12-20T12:04:00.002+08:002015-12-20T12:04:27.380+08:00php 偵測語系<div class="markdown">
```php
function getDefaultLanguage()
{
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
return parseDefaultLanguage($_SERVER['HTTP_ACCEPT_LANGUAGE']);
} else {
return parseDefaultLanguage(null);
}
}
function parseDefaultLanguage($http_accept, $deflang = 'zh-TW')
{
if (isset($http_accept) && strlen($http_accept) > 1) {
# Split possible languages into array
$x = explode(',', $http_accept);
foreach ($x as $val) {
#check for q-value and create associative array. No q-value means 1 by rule
if (preg_match("/(.*);q=([0-1]{0,1}.\d{0,4})/i", $val, $matches)) {
$lang[$matches[1]] = (float) $matches[2];
} else {
$lang[$val] = 1.0;
}
}
#return default language (highest q-value)
$qval = 0.0;
foreach ($lang as $key => $value) {
if ($value > $qval) {
$qval = (float) $value;
$deflang = $key;
}
}
}
return strtolower($deflang);
}
echo getDefaultLanguage();
```
</div>Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-91884327845382038392015-12-20T12:02:00.001+08:002015-12-20T12:03:05.537+08:00資料庫備份工具<div class="markdown">
```php
class DatabaseClone
{
public $link;
public function __construct($host, $username, $password)
{
$this->link = mysqli_connect($host, $username, $password);
mysqli_query($this->link, 'SET NAMES utf8');
mysqli_query($this->link, 'SET AUTOCOMMIT = 0');
mysqli_query($this->link, 'SET UNIQUE_CHECKS = 0');
mysqli_query($this->link, 'SET FOREIGN_KEY_CHECKS = 0');
}
public function fetch($query)
{
$results = [];
$query = mysqli_query($this->link, $query);
while ($row = mysqli_fetch_assoc($query)) {
$results[] = $row;
}
return $results;
}
public function copy($copyTo)
{
set_time_limit(-1);
ini_set('memory_limit', -1);
$query = mysqli_query($this->link, $sql = 'show databases');
while ($database = mysqli_fetch_assoc($query)) {
$database = $database['Database'];
if (in_array($database, ['mysql', 'information_schema', 'performance_schema'], true) === true) {
continue;
}
$createDatabase = mysqli_fetch_assoc(mysqli_query($this->link, 'SHOW CREATE DATABASE `'.$database.'`'));
mysqli_query($copyTo->link, $sql = 'DROP DATABASE IF EXISTS `'.$database.'`') or var_dump($sql);
mysqli_query($copyTo->link, $sql = $createDatabase['Create Database']) or var_dump($sql);
mysqli_select_db($this->link, $database);
mysqli_select_db($copyTo->link, $database);
$query2 = mysqli_query($this->link, $sql = 'show tables');
while ($table = mysqli_fetch_assoc($query2)) {
$table = current($table);
$createTable = mysqli_fetch_assoc(mysqli_query($this->link, 'SHOW CREATE TABLE `'.$table.'`'));
mysqli_query($copyTo->link, $sql = $createTable['Create Table']) or var_dump($sql);
$counts = current(mysqli_fetch_assoc(mysqli_query($this->link, 'SELECT COUNT(*) as counts FROM `'.$table.'`')));
$range = range(0, $counts - 1);
$offset = 0;
$limit = 200;
$chunks = array_chunk($range, $limit);
foreach ($chunks as $chunk) {
$query3 = mysqli_query($this->link, $sql = 'SELECT * FROM `'.$table.'` LIMIT '.$limit.' OFFSET '.$offset) or var_dump($database, $sql);
while ($row = mysqli_fetch_assoc($query3)) {
$keys = [];
$values = [];
foreach ($row as $key => $value) {
$keys[] = '`'.$key.'`';
$values[] = "'".addslashes($value)."'";
}
mysqli_query($copyTo->link, $sql = 'INSERT INTO `'.$table.'` ('.implode(',', $keys).') VALUES ('.implode(',', $values).')') or var_dump($database, $sql);
}
$offset += count($chunk);
}
}
}
}
}
$database = new DatabaseClone('localhost:3306', 'root', '');
$database->copy(new DatabaseClone('localhost:3308', 'root', ''));
```
</div>Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-61009124238599462152015-11-07T05:13:00.002+08:002015-11-07T05:15:41.680+08:00使用instance來進行Tracy Panel<div class="markdown">
```php
// PHP程式碼
include __DIR__.'/vendor/autoload.php';
use Tracy\Debugger;
use Tracy\IBarPanel;
class CustomPanel implements IBarPanel
{
/**
* Renders HTML code for custom tab.
* @return string
*/
public function getTab()
{
return 'sql';
}
/**
* Renders HTML code for custom panel.
* @return string
*/
public function getPanel()
{
$data = $this->data;
ob_start();
require __DIR__.'/custompanel.php';
return ob_get_clean();
}
public function push($data)
{
$this->data[] = $data;
}
public $data = [];
private static $_instance;
public static function instance()
{
if (static::$_instance === null) {
static::$_instance = new static;
}
return static::$_instance;
}
}
// 開發環境
$environment = Debugger::DEVELOPMENT;
// 啟用
Debugger::enable($environment);
Debugger::getBar()
->addPanel(CustomPanel::instance());
$i = 0;
CustomPanel::instance()->push([
'sql' => 'select * from user where id = '.++$i,
]);
CustomPanel::instance()->push([
'sql' => 'select * from user where id = '.++$i,
]);
CustomPanel::instance()->push([
'sql' => 'select * from user where id = '.++$i,
]);
```
```php
//樣板<h1>SQL</h1><br />
<br />
<div class="tracy-inner"><br />
<table><br />
<?php foreach ($data as $key => $value): ?><br />
<tr><td><?php echo $value['sql']; ?></td></tr><br />
<?php endforeach ?><br />
</table><br />
</div> ```
</div>
Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-4526788822613681942015-10-23T04:03:00.003+08:002015-10-24T08:30:06.925+08:00Laravel的Session不等於PHP Native Session<div class="markdown">
在Laravel內我們可能寫了以下的程式碼
```php
get('/session', function () {
session_start();
session()->put('foo', 'bar');
$_SESSION['foo'] = 'bar';
header('location: '.url('/session/display'));
exit;
});
get('/session/display', function () {
session_start();
ob_start();
dump(session()->get('foo'));
dump($_SESSION['foo']);
$content = ob_get_clean();
// output null, 'bar'
return $content;
});
```
會發現輸出結果完全不如我們所預期,為什麼會這樣呢?我們就好好的來做個探討吧...
## 原因出在Laravel的Session根本不是用PHP Native Session
在遇到這個狀況後,於是就去查了一下Laravel Session倒底是怎麼一回事,發現Laravel的程式碼內根本沒有執行session_start()啊
## Laravel Session倒底是怎麼運作的
追了一下Laravel的原始碼,發現它是利用[Illuminate\Session\Middleware\StartSession](https://github.com/illuminate/session/blob/master/Middleware/StartSession.php)來進行php session模擬的,
在Laravel執行的最後階段在將存在記憶體內的資料進行實體寫入,
所以只要在我們只要在程式內任意一個地方執行了php的exit, die, header('location: xxx');
那Session就不會被存入檔案內,自然在下一次連線也就取不到值了
## 有沒有解決方案
有,當然有,只要輸入
```php
get('/session', function () {
session_start();
session()->put('foo', 'bar');
$_SESSION['foo'] = 'bar';
session()->save(); // 手動寫入
dump($_SESSION['foo']);
$content = ob_get_clean();
// output 'bar', 'bar'
return $content;
});
```
## 後記
為什麼會有這一篇的出現,因為我們可能會用很多其它已經寫好的library,但它們就是有用到session_start();外加header, die, exit等等指令啊,所以記錄一下來提醒自己囉
</div>Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0tag:blogger.com,1999:blog-6534406401424841087.post-43315166829804775672015-09-20T18:12:00.000+08:002015-10-24T07:20:08.883+08:00重寫Laravel Socialite<div class="markdown">
最近需要用到OAuth的Client套件
所以就使用目前最多人使用的Laravel
不過需要的部份只有Laravel Socialite
看了一下composer.json的相依性
```json
"require": {
"php": ">=5.4.0",
"illuminate/contracts": "~5.0",
"illuminate/http": "~5.0",
"illuminate/support": "~5.0",
"guzzlehttp/guzzle": "~5.0|~6.0",
"league/oauth1-client": "~1.0"
},
```
只需要這些package並不需要整個Laravel
所以就開始使用它
不過在使用的過程遇到了不少問題
它所需要的package其實不止這些
所以程式在撰寫的過程中確實遇到不少問題
再在上在本機端上開發會遇到cURL error 60: SSL certificate problem
於是決定以[PHPoAuthLib](https://github.com/Lusitanian/PHPoAuthLib.git)進行開發
所以就寫了[Recca0120 Socialite](https://github.com/recca0120/Socialite)
並使它可以獨立使用
[Demo](https://github.com/recca0120/Socialite/tree/master/demo)
目前只先實作Laravel Socialite原本的功能,之後會視情形再加功能
OAuth1
BitBucket
Twitter
OAuth2
Facebook
GitHub
Google
Instagram
LinkedIn
</div>Anonymoushttp://www.blogger.com/profile/03749787361355769748noreply@blogger.com0