2
0

More than 1 year has passed since last update.

Rails を CakePHP4 に置き換えた時のメモ

Last updated at Posted at 2022-03-07

目的

CakePHP4の勉強がてら、Railsのプロジェクトを置き換える作業を実施した。

環境

Ruby On Rails 3.2.11
CakePHP 4.3.5

基本文法の比較

識別子

Ruby
local_var     # ローカル変数
@instans_var  # インスタンス変数
@@class_var   # クラス変数
$global_var   # グローバル変数
PHP
class Sample {
	// インスタンス変数
	static $instans_var;
	// クラス変数
	$class_var;
	public $public_class_var;
	private $private_class_var;

	function classMethod() {
		global $global_var;
		echo $global_var
		self::$instans_var = 'instans';
		$this->class_var = 'class';
		$local_var = 'local';
	}
}
$global_var = 'global';

echo Sample::$instans_var;

$sample = new Sample;
echo $sample->class_var; // クラス変数

文字列操作

Ruby
# 結合
str = str1 + str2
str += str3
# 部分取得
str = str[0,3]
# 分割
str = str.split(',')
PHP
# 結合
$str = $str1 . $str2;
$str .= $str3;
# 部分取得
$str = substr($str,0,3);
# 分割
$str = explode(',', $str);

配列

Ruby
# Array
ary = [1]
ary << 2       # [1,2]
ary.push 3, 4  # [1,2,3,4]
puts ary[0]    # 1

# Hash
h = {a:1, b:2}
h[:c] = 3      # {a:1, b:2, c:3}
PHP
# Array
$ary = [1];
$ary[] = 2;                // [1,2]
array_push($ary, 3, 4);    // [1,2,3,4]
puts $ary[0]l              // 1

# 連想配列
$h = ['a'=>1, 'b'=>2];
$h['c'] = 3;               // ['a'=>1, 'b'=>2, 'c'=>3]

if文

Ruby
if str.nil?
    # 処理1
elsif str.blank?
    # 処理2
else
    # 処理3
end
PHP
if (is_null($str)) {
    # 処理1
} else if ($str=="") {
    # 処理2
} else {
    # 処理3
}

for

Ruby
for i in 0..100 do
    # 処理
end
for row in data do
    # 処理
end
PHP
for ($i=0;$i<=100;$i++) {
    # 処理
}
foreach ($data as $row) {
    # 処理
}

each

Ruby
array.each do |val|
     # 処理
end
hash.each do |key, val|
     # 処理
end
hash.each_with_index do |val, i|
     # 処理
end
PHP
foreach ($hash as $val) {
    # 処理
}
foreach ($hash as $key => $val) {
    # 処理
}
foreach ($hash as $i => $val) {
    # 処理
}

関数定義

Ruby
def hello args
    # 処理
    ret # 戻り値
end
PHP
function hello($args) {
    # 処理
    return $ret; // 戻り値
}

クラス定義

Ruby
class ApplicationController < ActionController::Base
    NUMBER_1 = '1'

    def initialize(name)
       @name = name
    end

    def classmethod
      # 処理
    end

end   
PHP
class ApplicationController extends AppController
{
    const NUMBER_1 = '1';
    private $name;

    public function __construct($name){
      $this->name = $name;
    }

    public function classmethod(){
    }
}

フレームワークの比較

css, js の記述

Ruby
<%= stylesheet_link_tag "base.css" %>
<%= stylesheet_link_tag "jquery.css" %>

<%= javascript_include_tag "base.js" %>
<%= javascript_include_tag "jquery.js" %>
PHP
<?= $this->Html->css(['base', 'jquery']) ?>
<?= $this->fetch('css') ?>

<?= $this->Html->script(['base', 'jquery']) ?>
<?= $this->fetch('script') ?>

コントローラ共通モジュール(ヘルパー)

/app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  include CommonModule # /lib/common_module.rb
end
/src/Controller/ApplicationController.php
class ApplicationController < AppController
{
    public function initialize(): void
    {
        $this->loadComponent('CommonModule');
        $this->CommonModule->classMethod();
    }
}
/src/Controller/Component/CommonModuleComponent.php
namespace App\Controller\Component;
use Cake\Controller\Component;

class CommonModuleComponent extends Component {
	public function classMethod() {
	}
}

ビューでコントローラの共通モジュール(Component)を使う

/src/View/Helper/CommonModuleHelper.php
namespace App\View\Helper;
use Cake\View\Helper;
use App\Controller\Component\CommonModuleComponent;
use Cake\Controller\ComponentRegistry;

class CommonModuleHelper extends Helper
{
	function __call($methodName, $args) {
		$common = new CommonModuleComponent(new ComponentRegistry());
		return call_user_func_array(array($common, $methodName), $args);
	}
}

共通処理(before_filter)

/app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_filter :init, only=>[:hoge1, :hoge2]
  # 以下略
end
/src/Controller/ApplicationController.php
use Cake\Event\EventInterface;
class ApplicationController extends AppController {

public function beforeFilter(EventInterface $event)
{
	public function beforeFilter(EventInterface $event)
	{
		parent::beforeFilter($event);
		$action = $this->getRequest()->getParam('action');
		if (!in_array($action, ['hoge1', 'hoge2'])) return;
		$this->init();
	}
}

セッション

Ruby
# 代入・更新
session[:id] = 'hoge'
# 参照
@hoge = session[:id]
# 削除
session[:id].clear
session[:id] = nil
session.delete(:id)
# 全削除
reset_session
PHP
# セッションの取得
$session = $this->getRequest()->getSession();
# 代入・更新
$session->write('id', 'hoge');
# 参照
$hoge = $session->read('id');
# 存在し null ではない
$session->check('id');
# セッションの破棄
$session->destroy();

バイナリデータ出力(send_data)

Ruby
send_data(data, :type=>'application/octet-stream', :filename=>'ファイル名', :disposition=>'attachment')
PHP
	public function send_data($data, $options=[]) {
		$this->autoRender = false;
		$filename = $options['filename'];
        header("Content-type: ".$options['type']);	
		header('Content-Disposition: '.$options['disposition'].'; filename="'.$filename.'"');
		echo stream_get_contents($data);
		exit;
	}

Model

Railsと同名関数を使える共通モデルを作成

PHP
declare(strict_types=1);

namespace App\Model\Table;

use Cake\ORM\Table;

/**
 * Common Model
 */
class CommonTable extends Table
{
	public $connection;
    public function initialize(array $config): void
    {
        parent::initialize($config);
		$this->connection = \Cake\Datasource\ConnectionManager::get('default');
    }

	public function insert($params) {
		return $this->query()->insert(array_keys($params))->values($params)->execute();
	}

	# .delete_all(:conditions=>[])
	public function delete_all($conditions=[]) {
		return $this->query()->delete()->where($conditions)->execute();
	}

	# .update_all(params, :conditions=>[])
	public function update_all($params, $conditions=[]) {
		return $this->query()->update()->set($params)->where($conditions)->execute();
	}

	# .find_by_sql(sql)
	public function find_by_sql($sql) {
		return $this->connection->execute($sql)->fetchAll('assoc');
	}
	
	# .find('all', :condition=>[], :order->[], :select=>[])
	public function find_all($conditions=[], $order=[], $select=[]) {
		$query = $this->find('all', ['conditions'=>$conditions, 'order'=>$order]);
		if (!empty($select)) $query = $query->select($select);
		return $query->toList();
	}

	# .find('first', :condition=>[], :order->[])
	public function find_first($conditions=[], $order=[]) {
		return $this->find('all', ['conditions'=>$conditions, 'order'=>$order])->first();
	}
	# .exists(:conditions=>[])
	public function exists($conditions) : bool{
		return parent::exists($conditions);
	}
}

ビューヘルパー

Railsと同名関数を使える共通ヘルパーを作成

/src/View/Helper/RailsFormHelper.php
namespace App\View\Helper;

use Cake\View\Helper\FormHelper;
use Cake\View\StringTemplateTrait;

class RailsFormHelper extends FormHelper
{
    use StringTemplateTrait;

    protected $_defaultConfig = [
        'templates' => [
			'input' => '<input type="{{type}}" name="{{name}}" id="{{name}}"{{attrs}}/>',
		]
	];

	function hidden_field_tag($fieldName, $value) {
		return $this->hidden($fieldName, ['id'=>$fieldName, 'value'=>$value]);
	}
}
/src/View/Helper/RailsHtmlHelper.php
namespace App\View\Helper;

use Cake\View\Helper\HtmlHelper;
use Cake\View\StringTemplateTrait;

class RailsHtmlHelper extends HtmlHelper
{
    protected $_defaultConfig = [
        'templates' => [
            'image' => '<img src="{{url}}"{{attrs}}/>',
		]
	];

	// <?= image_tag("status1.png", :title => "保留する", :style => "cursor:pointer;", :onclick => "status1_click();")
	function image_tag($path, $options = []) {
		return $this->image($path, $options);
	}
}
/src/View/Helper/RailsUrlHelper.php
namespace App\View\Helper;

use Cake\View\Helper\UrlHelper;

class RailsUrlHelper extends UrlHelper
{

	function url_for($options = []) {
		$path = $options['controller'].'/'.$options['action'];
		$params = [];
		foreach ($options as $key => $val) {
			if (in_array($key, ['controller', 'action', 'anchor'])) {
				continue;
			}
			$params[] = $key.'='.$val;
		}
		if (!empty($params)) {
			$path .= '?'.implode('&', $params);
		}
		if (isset($params['anchor'])) {
			$path .= '#'.$params['anchor'];
		}

		return $this->build($path);
	}
}

コントローラからビューで使用する変数の設定

/app/controllers/test_controller.rb
class TestController < ActionController::Base
  def index
    @hoge = 'aaa'
  end 
end
/app/views/layouts/test/index.html.erb
<%= @hoge %>
/src/Controller/TestController.php
class TestController < AppController
{
    public function index()
    {
        $this->set('hoge', 'aaa');
    }
}
/templates/Test/index.php
<?= $hoge ?>

I18n

config/locales/ja.yml
ja:
  fruits:
    apple: "りんご"
    orange: "みかん"
<%= t("fruits.apple") %>
<%= t("fruits.orange") %>

CakePHPでyamlを使用できるようにする

/src/I18n/Parser/YamlFileParser.php
namespace App\I18n\Parser;

class YamlFileParser
{
    public function parse($file)
    {
        return yaml_parse_file($file);
    }
}

Railsと同様にインデントで階層を記述してみたところ、
うまく取得できなかったので、以下のように修正。
(原因については未調査)

/resources/locales/ja_JP/default.yaml
fruits.apple: "りんご"
fruits.orange: "みかん"
<?= __("fruits.apple") ?>
<?= __("fruits.orange") ?>

authenticity_token

パスワードのエンコード・デコード

備考

実際に置き換えた内容についてのみを記述しています。
不足分や必要があれば追記します。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0