Skip navigation

Category Archives: PHP


Just met a problem when I tried to serialize a PHP DateInterval object in HHVM (at least for 3.9.1). Turns out the DateInterval is unserializable. Create a bit workaround for this.

<?php

$dateinterval1 = new DateInterval('PT1H');
$baseDate = new DateTimeImmutable();
$date1 = $baseDate->add($dateinterval1);
$string1 = $dateinterval1->format('%y years %m months %d days %h hours %i minutes %s seconds');

$dateinterval2 = DateInterval::createFromDateString($string1);
$date2 = $baseDate->add($dateinterval2);

$string2 = $dateinterval2->format('%y years %m months %d days %h hours %i minutes %s seconds');
if ($string1 == $string2) {
    print "Formats are equal\n";
}
if ($date1 == $date2) {
    print "Objects are equal\n";
}
if ($date1->getTimestamp() == $date2->getTimestamp()) {
    print "Timestamp are equal\n";
}

The test can be seen here: https://3v4l.org/HvLFP

Iklan

To accept Angular $http.post that is formatted as JSON in Yii2, just set this in the Yii2 application component.

        'request' => [
            'parsers' => [
                'application/json' => 'yii\web\JsonParser',
            ]
        ],

To use the data, don’t use global $_POST. Instead use

$data = Yii::$app->getRequest->post();

Just another snippet. By using Chef’s PHP cookbook, we can easily install Zend Opcache. That if we still use PHP 5.4 since 5.5. have the opcache in the default distribution.

Put this in the recipe

php_pear "opcache" do
  package_name "ZendOpcache"
  action :install
  preferred_state "beta"
  zend_extensions ["opcache.so"]
  directives node['php']['opcache']['directives']
end

and this in the attributes

default['php']['opcache']['directives'] = {
    'memory_consumption' => 128,
    'interned_strings_buffer' => 8,
    'max_accelerated_files' => 4000,
    'revalidate_freq' => 60,
    'fast_shutdown' => 1,
    'enable_cli' => 1,
    'save_comments' => 0,   
}

This is just a very simple snippets, yet I can’t find it anywhere. I guess this rarely met.

Here’s how to use multiline input using Yii ConsoleCommand. In the console command class, use `$args` parameter in the console action.

public function actionIndex($args=array()){
   print_r($args)
}

Then you can execute something like command below which tries to input a JSON string to the console command.

$yii command index '{
   "name": "value"
}'

and the console will return

Array
(
    [0] => {
   "name": "value"
}
)

Kemarin saya sedang iseng membuka-buka StackOverflow dan menemukan pertanyaan ini Displaying CSV file content in Yii Framework’s CGridView.

Inti pertanyaannya adalah bagaimana menampilkan isi file CSV menggunakan GridView.

Cara mudahnya adalah dengan menggunakan CArrayDataProvider.

$file = fopen('test.csv', 'r');
$data = array();
while (($line = fgetcsv($file)) !== FALSE) {
    //$line is an array of the csv elements
    $data[] = $line;
}
fclose($file);
$columns = array();
foreach ($data[0] as $key => $value) {
    $columns[] = array(
        'name' => $key,
        'header' => $value,
    );
}
$data = array_slice($data, 1);
$dataProvider = new CArrayDataProvider($data, array(
    'keyField' => 0,
));
$this->widget('zii.widgets.grid.CGridView', array(
    'dataProvider' => $dataProvider,
    'columns' => $columns
));

Jika ingin menggunakan secara generik, kita bisa membuat kelas baru bernama CsvDataProvider.

class CsvDataProvider extends CArrayDataProvider {

    private $_columns = array();

    public function __construct($file, $config = array()) {
        $handler = fopen($file, 'r');
        $data = array();
        while (($line = fgetcsv($handler)) !== FALSE) {
            $data[] = $line;
        }
        fclose($handler);
        $this->_columns = array();
        foreach ($data[0] as $key => $value) {
            $this->_columns[] = array(
                'name' => $key,
                'header' => $value,
            );
        }
        $data = array_slice($data, 1);
        parent::__construct($data, array_merge($config, array(
            'keyField' => 0,
        )));
    }

    public function getColumns() {
        return $this->_columns;
    }
}

cara menggunakannya mudah

$dataProvider = new CsvDataProvider('file.csv');
$this->widget('zii.widgets.grid.CGridView', array(
    'dataProvider' => $dataProvider,
    'columns' => $dataProvider->getColumns(),
));

Tapi kode di atas belum bisa memfasilitasi sorting dan pagination. Kerugiannya juga adalah kinerja yang buruk jika digunakan pada berkas CSV berukuran sangat besar. Dan ada ide menarik untuk menggunakan library pemrosesan CSV yang hemat memori dan dengan fungsi lengkap. Nanti mungkin kalau sempat saya tuliskan penuhnya.


Bulan lalu saya diminta untuk mengisi acara Iftar untuk komunitas PHP Indonesia. Saya membawakan materi tentang “What’s New In Yii2” dan juga materi tambahan “What’s New In PHP 5.5”. Selain saya, ada juga pengisi lain yakni mas Iskandar Soesman dari Detik.com yang berbagi tentang “Optimize PHP Application in High Traffic Environment”.

PHP Meetup Indonesia

Berikut adalah slide dan videonya. Enjoy! Video-video dari acara PHP Indonesia lainnya dapat dilihat di link ini.


Pada postingan kali ini saya akan menuliskan bagaimana menggunakan AWS SDK for PHP version 2 pada Yii. Sebelum menggunakan yang versi 2, saya sudah menggunakan versi 1 dan versi kedua ini lebih mudah digunakan karena dia sudah mendukung pengaturan kode PHP yang sudah terstruktur sesuai dengan rekomendasi standar yang sedang tren yakni PSR. Oleh karena itu penggunaan SDK v2 ini dapat dilakukan dengan menggunakan Composer.

Cara instalasi program Composer untuk melakukan instalasi library AWS SDK, dapat dilihat di sini.

Seperti instalasi paket library ala Composer, pertama-tama kita membuat spesifikasi paket pada berkas “composer.json”. Untuk menambahkan AWS SDK, isi “composer.json” adalah sebagai berikut.

{
  "config": {
    "vendor-dir": "protected/composer/vendors"
  },
  "require": {
    "aws/aws-sdk-php": "2.3.*@dev"
  }
}

Sebenarnya konfigurasi Composer untuk instalasi SDK sudah cukup pada baris 5 sampai 7, tetapi saya pribadi lebih suka menambahkan konfigurasi untuk menyimpan library dari Composer pada direktori “protected/composer/vendors” agar tidak mengotori direktori lain seperti “protected/extensions” dan “protected/vendors“.

Setelah menambahkan konfigurasi tersebut, kita harus menjalankan perintah instalasinya.

petra@pc$composer install
Loading composer repositories with package information
Installing dependencies
  - Installing symfony/event-dispatcher (v2.2.1)
    Loading from cache

  - Installing guzzle/guzzle (v3.5.0)
    Loading from cache

  - Installing aws/aws-sdk-php (dev-master a299b46)
    Cloning a299b46693878b5a7ffaa30e236fbefe9113b6e0

symfony/event-dispatcher suggests installing symfony/dependency-injection (2.2.*)
symfony/event-dispatcher suggests installing symfony/http-kernel (2.2.*)
aws/aws-sdk-php suggests installing ext-apc (Allows service description opcode caching, request and response caching, and credentials caching)
aws/aws-sdk-php suggests installing doctrine/cache (Adds support for caching of credentials and responses)
aws/aws-sdk-php suggests installing monolog/monolog (Adds support for logging HTTP requests and responses)
aws/aws-sdk-php suggests installing symfony/yaml (Eases the ability to write manifests for creating jobs in AWS Import/Export)
Writing lock file
Generating autoload files

Sebelum bisa menggunakan composer, kita harus melakukan include untuk autoloading Composer.

require_once(dirname(__FILE__).'/protected/composer/vendors/autoload.php');
// change the following paths if necessary
$yii=dirname(__FILE__).'/yii/framework/yii.php';
$config=dirname(__FILE__).'/protected/config/main.php';

// remove the following lines when in production mode
defined('YII_DEBUG') or define('YII_DEBUG',true);
// specify how many levels of call stack should be shown in each log message
defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);

require_once($yii);
Yii::createWebApplication($config)->run();

Lalu kode di bagian controllernya seperti demikian

class SiteController extends Controller
{

    public function actionIndex()
    {
        if (Yii::app()->request->getIsPostRequest()) {
            $file = CUploadedFile::getInstanceByName('file');
            /* @var $file CUploadedFile */
            if (isset($file)) {
                $s3 = \Aws\S3\S3Client::factory(array(
                        'key' => 'YourAWSKEY',
                        'secret' => 'YourAWSSecret',
                        'region' => \Aws\Common\Enum\Region::SINGAPORE,
                    ));
                /* @var $s3 Aws\S3\S3Client */
                try {
                    $result = $s3->putObject(array(
                        'Bucket' => 'bucketname',
                        'Key' => $file->name,
                        'SourceFile' => $file->tempName,
                        ));
                    /* @var $result \Guzzle\Service\Resource\Model */
                    $url = $result->get("ObjectURL");
                    Yii::app()->user->setFlash('Success', "Upload Success: " . CHtml::link($url, $url));
                } catch (\Aws\S3\Exception\S3Exception $exc) {
                    /* @var $exc \Aws\S3\Exception\S3Exception */
                    $message = $exc->getMessage();
                    Yii::app()->user->setFlash('Failed', "Upload Failed: {$message}");
                }
            }
        }
        $this->render('index');
    }

}

Bagian controller akan menangani request dari upload form kemudian melakukan pengunggahan ke S3. Untuk pengunggahan kita memerlukan kelas S3Client dari AWS SDK. Pada instansiasinya kita perlu mengeset key dan secret dari akun AWS yang dimiliki, serta region tempat penyimpanan.

Lalu proses pengunggahan sendiri akan dilakukan dengan menginvokasi method putObjectObyek yang dikembalikan oleh method ini hanya berupa model yang berisi return value dari invokasi HTTP request yang dilakukan oleh Guzzle. Untuk mengambil URL dari file yang telah diunggah, kita ambil saja atribut ObjectURL pada model tersebut.

Bagian viewnya sangat sederhana.

<h1>Upload file</h1>

<?php if (Yii::app()->user->hasFlash('Success')): ?>
    <div class="flash-success">
        <?php echo Yii::app()->user->getFlash('Success'); ?>
    </div>
<?php endif; ?>
<?php if (Yii::app()->user->hasFlash('Failed')): ?>
    <div class="flash-error">
        <?php echo Yii::app()->user->getFlash('Success'); ?>
    </div>
<?php endif; ?>

<?php echo CHtml::beginForm('', 'post', array('enctype' => 'multipart/form-data')); ?>
<?php echo CHtml::fileField('file'); ?>
<?php echo CHtml::submitButton(); ?>
<?php echo CHtml::endForm(); ?>

Nanti hasilnya akan seperti demikian.

Tampilan Sebelum Pengunggahan

Tampilan Sebelum Pengunggahan

Setelah melakukan pengunggahan, dia akan menampilkan URL yang telah disimpan oleh setFlash.

Tampilan Setelah Pengunggahan

Tampilan Setelah Pengunggahan

Dan di AWS S3 console, sudah bisa dilihat di dalam bucketnya kalau filenya sudah diunggah.

Isi Bucket Setelah Pengunggahan

Isi Bucket Setelah Pengunggahan

AWS SDK for PHP version 2 ini jauh lebih enak digunakan daripada versi sebelumnya karena sudah memenuhi standar PSR sehingga bisa digunakan dengan Composer serta dengan mudah diintegrasikan pada aplikasi Yii. Selain S3, SDK ini juga menyediakan banyak library untuk layanan AWS lainnya seperti EC2, DynamoDB, dll.

Kodenya dapat dilihat di link ini.

Failed

Kemarin sore saya ingin membuat bot twitter yang bisa mengupdate status twitter setiap jam. Dan caranya ternyata sangat mudah. Cukup unduh library Twitter OAuth di sini kemudian extract di “/protected/vendors/twitteroauth”.

jadinya seperti ini

$ls protected/vendors/twitteroauth
-rw-rw-r-- 1 petra petra 26482 May  4 10:12 OAuth.php
-rw-rw-r-- 1 petra petra  7755 May  4 10:12 TwitterOAuth.php

bagi yang menggunakan server berbasis *NIX (yang case sensitive) ubah nama file twitteroauth.php menjadi TwitterOAuth.php

Sekarang tinggal membuatconsole commanddi “protected/commands”

<?php
class TweetbotCommand extends CConsoleCommand {

        const CONSUMER_KEY = 'xxxxxxxxxxxxxxxxx';
        const CONSUMER_SECRET = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
        const OAUTH_TOKEN = 'xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
        const OAUTH_SECRET = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

        public function actionTweet() {
                $message = "Hello World!";

                Yii::import('application.vendors.twitteroauth.*');
                $connection = new TwitterOAuth(self::CONSUMER_KEY, self::CONSUMER_SECRET, self::OAUTH_TOKEN, self::OAUTH_SECRET);
                $connection->get('account/verify_credentials');
                $connection->post('statuses/update', array('status' => $message));
        }

}

Untuk isi dari variabel CONSUMER_KEY, CONSUMER_SECRET, OAUTH_TOKEN, dan OAUTH_SECRET bisa dilihat di panduan ini.

Sekarang untuk menjalankannya tinggal eksekusi YIIC saja.

$/usr/bin/php protected/yiic tweetbot tweet
$#atau bisa cara di bawah
$php protected/yiic tweetbot tweet
$#atau juga bisa cara di bawah
$protected/yiic tweetbot tweet

Dan dengan mudahnya agar tweetnya bisa diupdate setiap jam adalah dengan menambahkan entri di crontab

0 * * * * * /usr/bin/php protected/yiic tweetbot tweet

(Karena terlalu simpel, kodenya tidak saya masukkan di github)


Sesuai dengan permintaan di postingan sebelumnya, sekarang saya akan mencoba menambahkan link di dropdown yang dihasilkan oleh autocomplete. Seperti autocomplete yang ada di Facebook, autocomplete yang akan saya modifikasi akan memindahkan halaman ke halaman profil userketika dropdownnya diklik.

Read More »


Setelah di postingan sebelumnya menjelaskan tentang cara penggunaan CJuiAutoComplete secara sederhana, postingan ini akan mencoba menyambungkan autocomplete tersebut dengan database.

Read More »

%d blogger menyukai ini: