質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

2回答

637閲覧

PHPでclassの状態遷移にガードを追加したい

tomoyuki123

総合スコア273

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2020/08/25 02:35

編集2020/08/25 04:20

質問概要

Rubyだと以下のようなgemがあるんですが、PHPで同様のことを実現させる方法がわかりません。

https://github.com/aasm/aasm#guards

ruby

1 event :clean_if_needed do 2 transitions from: :idle, to: :cleaning do 3 guard do 4 cleaning_needed? 5 end 6 end 7 transitions from: :idle, to: :idle 8end

以下のようなものを使えばいいかと思ったのですが、readmeを読んだり実際に使った感じだとできないようでした。
https://github.com/myclabs/php-enum

どなたかPHPで実現させる方法があれば教えてください。

やりたいこと

記事にステータス(公開、非公開、削除)を持たせて、削除したものは公開できないようにしたい。

聞きたいこと

削除した記事を公開しようとした時に、例外発生させるなどロジックで解決はできますが
状態遷移を管理するライブラリなどがあれば教えていただきたいです。
ライブラリがなければこういった要件の実装のベストプラクティスがあれば知りたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2020/08/25 03:44 編集

rubyがわからないのでなんとも言えませんが、それはphpに必要な機能なのでしょうか? 言語の成り立ちもちがうので具体的になにをどうしたいか書いたほうがよいかと・・・
tomoyuki123

2020/08/25 04:20

ありがとうございます。 PHPに必要かどうかと言われるとわからないのですが、具体的にやりたいことを追記しました。
退会済みユーザー

退会済みユーザー

2020/08/26 13:10

よく知らないし、使ったこともないですが、キーワードでググっただけのものを紹介します。 https://github.com/winzou/state-machine Laravel用のものもあるようです。
tomoyuki123

2020/08/27 02:28

ありがとうございます!
guest

回答2

0

ベストアンサー

https://github.com/winzou/state-machine
コメントしたけど反応ないので適当に書いてみました。
エスケープしないでHTMLに変数出力してるので、そのまま使わないでください。

app/sample.php

php

1<!DOCTYPE html> 2<html lang="ja"> 3<head> 4<meta charset="utf-8"></head> 5</head> 6<body> 7<?php 8require('vendor/autoload.php'); 9 10class SampleState { 11 private $state = 'private'; 12 13 public function getState() 14 { 15 return $this->state; 16 } 17 18 public function setState($state) 19 { 20 $this->state = $state; 21 } 22} 23 24function isAdministrator() { 25 return ($_REQUEST['admin'] ?? false); 26} 27 28$config = array( 29 'graph' => 'myGraph', 30 'property_path' => 'state', 31 'states' => array( 32 'private', 33 'public', 34 'deleted' 35 ), 36 'transitions' => array( 37 'publish' => array( 38 'from' => array('private'), 39 'to' => 'public' 40 ), 41 'secret' => array( 42 'from' => array('public'), 43 'to' => 'private' 44 ), 45 'delete' => array( 46 'from' => array('public', 'private'), 47 'to' => 'deleted' 48 ), 49 'revive' => array( 50 'from' => array('deleted'), 51 'to' => 'private' 52 ) 53 ), 54 'callbacks' => array( 55 'guard' => array( 56 'guard-cancel' => array( 57 'from' => array('deleted'), 58 'do' => function() { 59 return isAdministrator(); 60 } 61 ) 62 ) 63 ) 64); 65 66// リクエストの読み取り 67$reqState = $_REQUEST['state'] ?? "private"; 68$reqEvent = $_REQUEST['event'] ?? "secret"; 69 70// 遷移 71$state = new SampleState(); 72$state->setState($reqState); 73$stateMachine = new \SM\StateMachine\StateMachine($state, $config); 74$stateMachine->apply($reqEvent, true); 75 76// 表示 77?> 78<form> 79<div> 80<span>state:</span><span><?php 81printf('%s<input type="hidden" name="state" value="%s"></input>', $state->getState(), $state->getState()); 82?></span> 83</div> 84<div> 85<span>event:</span><span><?php 86foreach($config['transitions'] as $e => $v) { 87 $checked = ($reqEvent === $e) ? " checked" : ""; 88 printf('<input type="radio" name="event" value="%s"%s>%s</input>', $e, $checked, $e); 89} 90?></span> 91</div> 92<div><?php 93printf('<input type="checkbox" name="admin"%s>administrator</input>', ($_REQUEST['admin'] ?? false) ? " checked" : ""); 94?></div> 95<div> 96<button type="submit">submit</button> 97</div> 98</form> 99</body> 100</html>

docker用環境構築向け

docker-compose.yml

yaml

1version: "3" 2 3services: 4 php: 5 build: ./docker/php 6 volumes: 7 - ./app:/var/www/html/ 8 - ./php.ini:/usr/local/etc/php/php.ini 9 ports: 10 - "8011:80" 11 composer: 12 image: composer 13 command: 'composer update' 14 volumes: 15 - ./app:/app 16 links: 17 - php

php.ini

ini

1post_max_size = 50M 2upload_max_filesize = 50M 3memory_limit = 256M 4[xdebug] 5xdebug.remote_enable=1 6xdebug.remote_autostart=1 7xdebug.remote_host=[***YOUR HOST IP ADDRESS***] 8xdebug.remote_port=9000 9xdebug.remote_log=/tmp/xdebug.log 10zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20190902/xdebug.so

※zend_extensionは新しくなると変わります。ビルド時のメッセージを良く見ましょう

docker/php/Dockerfile

Dockerfile

1FROM php:7-apache 2 3RUN pecl install xdebug \ 4 && docker-php-ext-enable xdebug 5CMD ["apache2-foreground"]

create_env.sh

sh

1docker-compose run composer require winzou/state-machine 2docker-compose down 3docker-compose up -d 4# http://localhost:8011/sample.php

.vscode/launch.json

json

1{ 2 "version": "0.2.0", 3 "configurations": [ 4 { 5 "name": "Listen for XDebug", 6 "type": "php", 7 "request": "launch", 8 "port": 9000, 9 "pathMappings": { 10 "/var/www/html":"${workspaceRoot}/app" 11 } 12 } 13 ] 14}

投稿2020/08/26 22:26

編集2020/08/26 22:44
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/09/02 13:19

低評価頂くのは別にいいのですが、理由も書かずに低評価されても対応できません。 低評価までするなら堂々と理由もお書きください。書かない場合は無条件に私怨と見做します。
guest

0

言語の問題ではないように感じますが・・・
RDBでフラグ管理すれば良いと思います
(削除が物理削除か論理削除にもよりそうです)

投稿2020/08/25 04:24

yambejp

総合スコア116724

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問