Skip to content

Commit

Permalink
Modelをリファクタリング
Browse files Browse the repository at this point in the history
  • Loading branch information
fumikito committed Dec 17, 2014
1 parent 4d87237 commit a608d26
Show file tree
Hide file tree
Showing 3 changed files with 259 additions and 38 deletions.
6 changes: 3 additions & 3 deletions freundschaft.php
Expand Up @@ -76,7 +76,7 @@ function _freundschaft_logged_in(){
$users = array(); $users = array();
if( isset($_POST['author_ids']) && is_array($_POST['author_ids'])){ if( isset($_POST['author_ids']) && is_array($_POST['author_ids'])){
$author_ids = array_unique($_POST['author_ids']); $author_ids = array_unique($_POST['author_ids']);
$result = Freundschaft\Model\Followers::getInstance()->getFollowStatus(get_current_user_id(), $author_ids); $result = Freundschaft\Models\Followers::getInstance()->getFollowStatus(get_current_user_id(), $author_ids);
$users = array(); $users = array();
foreach( $result as $user_id => $bool ){ foreach( $result as $user_id => $bool ){
$users['user_'.$user_id] = $bool; $users['user_'.$user_id] = $bool;
Expand Down Expand Up @@ -117,7 +117,7 @@ function _freundschaft_follow(){
if( !isset($_POST['user_id']) || !is_numeric($_POST['user_id']) ){ if( !isset($_POST['user_id']) || !is_numeric($_POST['user_id']) ){
throw new Exception('ユーザーIDが指定されていません。', 500); throw new Exception('ユーザーIDが指定されていません。', 500);
} }
if( !Freundschaft\Model\Followers::getInstance()->follow(get_current_user_id(), $_POST['user_id']) ){ if( !Freundschaft\Models\Followers::getInstance()->follow(get_current_user_id(), $_POST['user_id']) ){
throw new Exception('すでにフォローしています。', 500); throw new Exception('すでにフォローしています。', 500);
} }
$json = array( $json = array(
Expand Down Expand Up @@ -148,7 +148,7 @@ function _freundschaft_unfollow(){
if( !isset($_POST['user_id']) || !is_numeric($_POST['user_id']) ){ if( !isset($_POST['user_id']) || !is_numeric($_POST['user_id']) ){
throw new Exception('ユーザーIDが指定されていません。', 500); throw new Exception('ユーザーIDが指定されていません。', 500);
} }
if( !Freundschaft\Model\Followers::getInstance()->unfollow(get_current_user_id(), $_POST['user_id']) ){ if( !Freundschaft\Models\Followers::getInstance()->unfollow(get_current_user_id(), $_POST['user_id']) ){
throw new Exception('このユーザーをフォローしていません。', 500); throw new Exception('このユーザーをフォローしていません。', 500);
} }
$json = array( $json = array(
Expand Down
@@ -1,21 +1,29 @@
<?php <?php


namespace Freundschaft\Model; namespace Freundschaft\Models;


use Freundschaft\Pattern\Singleton; use Freundschaft\Pattern\Model;




/** /**
* Followers Model * Followers Model
* *
* @package Freundschaft\Model * @package Freundschaft\Model
* @property-read \wpdb $db
* @property-read string $table
*/ */
class Followers extends Singleton class Followers extends Model
{ {


protected $columns = array(
'follower_id' => '%d',
'user_id' => '%d',
'created' => '%s',
);

protected $timestamp_on_create = 'created';

/** /**
* Get following status of * Get following status of specified user ids
* *
* @param int $follower_id * @param int $follower_id
* @param array $user_ids * @param array $user_ids
Expand All @@ -36,7 +44,7 @@ public function getFollowStatus($follower_id, $user_ids = array()){
AND user_id in ({$where_in}) AND user_id in ({$where_in})
SQL; SQL;
// Get result as array // Get result as array
$result = $this->db->get_col($this->db->prepare($query, $follower_id)); $result = $this->get_col($query, $follower_id);
// Make return array['user_id' => true|false] // Make return array['user_id' => true|false]
$return = array(); $return = array();
foreach( $user_ids as $user_id){ foreach( $user_ids as $user_id){
Expand All @@ -57,11 +65,10 @@ public function getFollowStatus($follower_id, $user_ids = array()){
* @return bool * @return bool
*/ */
public function follow($follower_id, $user_id){ public function follow($follower_id, $user_id){
return (bool) $this->db->insert($this->table, array( return (bool) $this->insert(array(
'follower_id' => $follower_id, 'follower_id' => $follower_id,
'user_id' => $user_id, 'user_id' => $user_id,
'created' => current_time('mysql'), ));
), array('%d', '%d', '%s'));
} }


/** /**
Expand All @@ -73,32 +80,9 @@ public function follow($follower_id, $user_id){
* @return bool * @return bool
*/ */
public function unfollow($follower_id, $user_id){ public function unfollow($follower_id, $user_id){
return (bool) $this->db->delete($this->table, array( return (bool) $this->delete(array(
'follower_id' => $follower_id, 'follower_id' => $follower_id,
'user_id' => $user_id, 'user_id' => $user_id,
), array('%d', '%d')); ));
}

/**
* Getter
*
* @param string $name
*
* @return null
*/
public function __get( $name ){
switch( $name ){
case 'db':
global $wpdb;
return $wpdb;
break;
case 'table':
return $this->db->prefix.'followers';
break;
default:
return null;
break;
}
} }

} }
237 changes: 237 additions & 0 deletions src/Freundschaft/Pattern/Model.php
@@ -0,0 +1,237 @@
<?php

namespace Freundschaft\Pattern;

/**
* Abstract class of Model
*
* @package Freundschaft\Pattern
* @property-read \wpdb $db
* @property-read string $table
* @method int query(string $query) Do $wpdb->query with prepared statement.
* @method array get_results(string $query) Do $wpdb->get_result with prepared statement.
* @method null|\stdClass get_row(string $query) Do $wpdb->get_result with prepared statement.
* @method string get_var(string $query) Do $wpdb->get_var with prepared statement.
* @method array get_col(string $query) Do $wpdb->get_col with prepared statement.
*/
abstract class Model extends Singleton
{

/**
* @var string
*/
protected $name = '';

/**
* @var array
*/
protected $columns = array();

/**
* Column to auto insert current timestamp
*
* @var string
*/
protected $timestamp_on_create = '';

/**
* Column name to auto update current timestamp
*
* @var string
*/
protected $timestamp_on_update = '';

/**
* If true, this table will be unique on multi site
*
* @var bool
*/
protected $unique_on_multisite = false;

/**
* Constructor
*
* @param array $settings
*/
protected function __construct( array $settings = array() ) {
// Set table name
if( empty($this->name) ){
$name = explode('\\', get_called_class());
$this->name = $this->decamelize($name[count($name) - 1]);
}
}

/**
* Check model setting
*
* @return bool|\WP_Error
*/
public function test_setting(){
$error = new \WP_Error();
// Trigger error if $columns is empty
if( empty($this->columns) ){
$error->add(500, sprintf('Modelのサブクラス%sは必ず$columnsを設定しなければなりません。', get_called_class()));
}else{
$invalid_columns = array();
foreach( $this->columns as $column => $place_holder ){
if( false === array_search($place_holder, array('%s', '%d', '%f')) ){
$invalid_columns[] = $column;
}
}
if( !empty($invalid_columns) ){
$error->add(500, sprintf('Modelのサブクラス%sは必ず$columnsを設定しなければなりません。', get_called_class()));
}
}
// Check table name
if( !preg_match('/\A[a-zA-Z_0-9]+\z/', $this->table) ){
$error->add(500, sprintf('テーブル名%sには英数字とアンダースコア以外が含まれています。', $this->table));
}
return $error->get_error_messages() ? $error : true;
}

/**
* Insert data
*
* @param array $values
*
* @return false|int
*/
public function insert( array $values ){
$data = $this->get_value_and_where($values);
if( !empty($this->timestamp_on_create) ){
if( !isset($data['values'][$this->timestamp_on_create]) ){
// Add current time to values
$data['values'][$this->timestamp_on_create] = current_time('mysql');
$data['wheres'][] = $this->columns[$this->timestamp_on_create];
}
}
return $this->db->insert($this->table, $data['values'], $data['wheres']);
}

/**
* Update
*
* @param array $values
* @param array $where
*
* @return false|int
*/
public function update( array $values, array $where ){
$data = $this->get_value_and_where($values);
if( !empty($this->timestamp_on_update) ){
if( !isset($data['values'][$this->timestamp_on_update]) ){
// Add current time to values
$data['values'][$this->timestamp_on_update] = current_time('mysql');
$data['wheres'][] = $this->columns[$this->timestamp_on_update];
}
}
$wheres = $this->get_value_and_where($where);
return $this->db->update($this->table, $data['values'], $wheres['values'], $data['wheres'], $wheres['wheres']);
}

/**
* Delete
*
* @param array $where
*
* @return false|int
*/
public function delete( array $where ){
$wheres = $this->get_value_and_where($where);
return $this->db->delete($this->table, $wheres['values'], $wheres['wheres']);
}


/**
* Get values and wheres
*
* @param array $data
*
* @return array ['values' => [], 'wheres' => []]
* @throws \InvalidArgumentException
*/
protected function get_value_and_where( array $data ){
if( empty($data) ){
throw new \InvalidArgumentException('配列が空です。', 500);
}
$values = array();
$wheres = array();
foreach( $data as $column_name => $value ){
// Throw exception if invalid columns name is past.
if( !isset($this->columns[$column_name]) ){
throw new \InvalidArgumentException(sprintf('存在しないカラム%sが指定されています。', $column_name), 500);
}
// Create wheres.
$values[$column_name] = $value;
$wheres[] = $this->columns[$column_name];
}
return compact('values', 'wheres');
}

/**
* Make upper came to snake case
*
* @param string $string
*
* @return string
*/
protected function decamelize($string){
return strtolower(preg_replace_callback('/(?<=.)([A-Z])/', function($match){
return '_'.strtolower($match[1]);
}, $string));
}

/**
* Getter
*
* @param string $name
*
* @return null
*/
public function __get( $name ){
switch( $name ){
case 'db':
global $wpdb;
return $wpdb;
break;
case 'table':
if( is_multisite() && $this->unique_on_multisite){
return $this->db->base_prefix.$this->name;
}else{
return $this->db->prefix.$this->name;
}
break;
default:
return null;
break;
}
}

/**
* Method overload
*
* @param string $name
* @param array $arguments
*
* @return mixed
*/
public function __call($name, $arguments = array()){
switch( $name ){
case 'get_var':
case 'get_result':
case 'get_row':
case 'get_col':
case 'query':
if( count($arguments) > 1 ){
return call_user_func_array(array($this->db, $name), array(call_user_func_array(array($this->db, 'prepare'), $arguments)));
}else{
return call_user_func_array(array($this->db, $name), $arguments);
}
break;
default:
// Do nothing
break;
}
}

}

0 comments on commit a608d26

Please sign in to comment.