신규 모듈 제작시 항상 XML 쿼리를 만드는게 귀찮았습니다.

 

맨날 똑같은 작업을 반복하다보니 생산성도 안나오고 진절머리가 나서 자동 생성 툴을 만들었습니다

 

 

gen.png.jpg

 

테이블의 XML 쿼리를 입력해주면 자동으로 생성해줍니다.

 

primary_key가 없다면 작동하지 않으니 그냥 하나 생성해주세요.

 

primary_key가 없다면 "검색 조건 컬럼" 항목에 condition 절에 들어갈 컬럼을 입력해주세요.

그러나 사용할 일이 없더라도 auto_increment등을 활용하여 primary_key 컬럼을 만드는것을 권장합니다. (성능상 이점, 관리 용이)

 

https://tools.hoshi.no/crud_generator.php

 

소스코드 : https://github.com/Waterticket/rx-crud-generator

+) 작은 프로젝트일줄 알고 발코딩했는데, 이렇게 커질줄 몰랐네요;

리버스

profile
모듈 제작하는 현역 대학생 리버스입니다!

== 판매중인 모듈 ==
미션] https://xetown.com/thirdparties/1511787
길드] https://xetown.com/thirdparties/1387146
  • profile

    hotoboard_documents 테이블에는 document들이 들어갈 테니, 단수 복수 자동 변환해서 getDocument (1개 가져오기), getDocuments (여러 개 가져오기), getDocumentList (정렬+페이징 부분 적당히 넣어주기) 등의 배리에이션까지 생성해 준다면 더욱 좋겠네요!

     

    regdate라는 컬럼이 있으면 insert할 때 default="curdate()"를 넣어주고, ipaddress 컬럼은 default="ipaddress()"를 넣어주고, primary key가 auto_increment인 경우 insert시 제외하고, 등등... 당연히 있어야 하는 코드인데 일일이 써넣기 귀찮은 것이 참 많아요.

     

    귀차니즘이 더 심해지면 아예 각각의 쿼리에 해당하는 model 함수까지 만들어 버리실지도...

    (칭찬을 빙자한 일감투척 ㅋㅋㅋ)

  • profile profile
    말씀하신 부분 수정했습니다 :D

    model 함수까지 만든다라.. 상당히 끌리네요 ㅋㅋ
  • profile profile

    screencapture-ichika-hoshi-no-tools-crud-generator-php-2022-07-16-02_00_46.png.jpg

     

    PHP 구문까지 패치해보았습니다.

     

    다른 부분은 괜찮은데 get 파트에서 약간 의문이 들더라고요

     

    쿼리를 정상적으로 실행하면 data를 리턴하는데, 쿼리 실패시 $output을 그대로 리턴하다보니 문제가 발생할거 같더군요

     

    이 부분은 어떤식으로 처리하는게 좋을까요?

     

     

    +)

    Update 쿼리에서 특정 컬럼만 업데이트 할 수 있도록 notnull 조건을 빼주었습니다.

     

    그런데 여기서도 의문이 있더라고요


    만약 column 변수에 null이 들어있다면, 해당 쿼리는 null로 변경되나요? 아니면 기존 값이 유지되나요

    ex) updateDocument 함수에서, document_srl, product_srl에는 값이 있으나, $obj->regdate에는 값을 넣지 않았을 경우

    쿼리 실행 후 DB에는 regdate값이 유지되나요?

     

     

     

    Ps. 이건 간단히 만들고 만들던 모듈 이어서 만드려고 했는데, 시간이 훅훅 지나가네요 ㅋㅋ

  • profile profile

    하나의 함수가 여러 가지 자료형을 반환할 수 있다면 잘못 설계된 것입니다. 예전에 XE에서 이상하게 만들어 놓는 바람에 다들 그걸 따라하고 있는데, 상식적으로 getDocument는 object를 반환하고 getDocuments는 array를 반환하고 getDocumentList는 $output에 다 담아서 반환하는 것이 정상이지요. 결과의 상태나 갯수에 따라 자료형이 달라지면 안됩니다. 쿼리 실패와 같이 "예외적인" 상황에서는 Exception을 던지면 됩니다.

    함수의 인자로 $obj를 받는 것도 골때리는 관례입니다. 그 안에 무엇이 들어가야 하는지 에디터가 자동 인식할 수 없기 때문에 코딩할 때 안내가 되지 않아서 불편합니다. getDocument는 int $document_srl을 받고, getDocuments는 array $document_srl(s)를 받고, getDocumentList처럼 조건이 복잡한 경우에만 오브젝트를 받으면 됩니다. insert, update는 $obj를 받아도 되고, delete도 1개뿐이라면 int $document_srl을 받고요. 만약 오브젝트를 받았다면 뭔가 검증이 필요한 경우를 제외하면 $args에 일일이 옮겨담을 필요는 없습니다.

    PHP 7.0부터 함수의 인자와 결과값 모두의 자료형을 선언할 수 있게 되었습니다.

    예:
    public function getDocument(int $document_srl): DocumentItem
    public function getDocuments(array $document_srls): array

    부득이하게 null이나 false를 반환해야 하는 경우를 제외하면, 이런 식으로 선언할 수 있을 만큼 인자와 결과값이 일정한 것이 좋습니다. 물론 Exception은 말 그대로 "예외"이므로 뭐든지 던져도 됩니다.

    update시 $args->변수에 null을 집어넣으면 1) notnull="notnull"로 선언된 경우 에러가 나고, 2) default값이 선언된 경우 그 값으로 업데이트되고, 3) 그렇지 않으면 해당 컬럼은 업데이트하지 않습니다.

  • profile profile

    1. 한 함수는 자료형 하나 반환하는게 맞는데, 기존의 소스들을 찾아봐도 다른 방식으로 구현한게 안보여서 그렇게 구현했습니다. 지금은 한 함수에 하나의 자료형만 반환하도록 변경하였습니다.

    2. DB 에러시 throw new \Rhymix\Framework\Exceptions\DBError($output->getMessage()) 를 던지도록 해두었는데, 이렇게 하면 일반 유저에게도 에러 메세지가 보이더라고요?
    위와 같이 구현하는게 맞을까요?

    3. 혹시 모르는 오류 상황을 방지하기 위해서 $args 변수에 값들을 옮기도록 설정했는데, 컬럼이 변경되거나 Update시에 상황을 처리하기 난해해지더군요. 그래서 말씀하신대로 $obj를 받는 함수들은 해당 object를 그대로 쿼리에 집어넣도록 변경하였습니다.

    4. 또한 굳이 $obj를 받지 않아도 되는 getDocument, getDocuments, deleteDocument와 같은 함수들은 파라메터에 해당 값을 바로 받도록 변경하였습니다.

     

    /**
     * hotoboard_documents 테이블에 Document 하나를 추가한다.
     * 
     * @param object $obj
     */
    public static function insertDocument(object $obj): object
    {
        $oDB = DB::getInstance();
        $oDB->begin();
    
        $output = executeQuery('hotoboard.insertDocument', $obj);
        if(!$output->toBool())
        {
            $oDB->rollback();
            throw new \Rhymix\Framework\Exceptions\DBError($output->getMessage());
        }
        $oDB->commit();
    
        return new BaseObject();
    }
    
    /**
     * hotoboard_documents 테이블에서 Document를 가져온다.
     * 
     * @param int $document_srl
     */
    public static function getDocument(int $document_srl): object
    {
        $args = new stdClass();
        $args->document_srl = $document_srl;
    
        $output = executeQuery('hotoboard.getDocument', $args);
        if(!$output->toBool())
        {
            throw new \Rhymix\Framework\Exceptions\DBError($output->getMessage());
        }
    
        return $output->data;
    }
    
    /**
     * hotoboard_documents 테이블에서 Document 여러 건을 가져온다.
     * 
     * @param array $document_srl
     */
    public static function getDocuments(array $document_srl): array
    {
        $args = new stdClass();
        $args->document_srl = $document_srl;
    
        $output = executeQueryArray('hotoboard.getDocuments', $args);
        if(!$output->toBool())
        {
            throw new \Rhymix\Framework\Exceptions\DBError($output->getMessage());
        }
    
        return $output->data;
    }
    
    
    /**
     * hotoboard_documents 테이블에서 Document를 리스트 형식으로 가져온다.
     * 
     * @param object $obj
     */
    public static function getDocumentList(object $obj): object
    {
        $obj->sort_index = $obj->sort_index ?? 'document_srl';
        $obj->order_type = $obj->order_type ?? 'desc';
        $obj->list_count = $obj->list_count ?? 20;
        $obj->page_count = $obj->page_count ?? 10;
        $obj->page = $obj->page ?? 1;
    
        $output = executeQueryArray('hotoboard.getDocumentList', $obj);
        if(!$output->toBool())
        {
            throw new \Rhymix\Framework\Exceptions\DBError($output->getMessage());
        }
    
        return $output;
    }
    
    
    /**
     * hotoboard_documents 테이블에서 Document를 업데이트한다.
     * 
     * @param object $obj
     */
    public static function updateDocument(object $obj): object
    {
        $oDB = DB::getInstance();
        $oDB->begin();
    
        $output = executeQuery('hotoboard.updateDocument', $obj);
        if(!$output->toBool())
        {
            $oDB->rollback();
            throw new \Rhymix\Framework\Exceptions\DBError($output->getMessage());
        }
        $oDB->commit();
    
        return new BaseObject();
    }
    
    /**
     * hotoboard_documents 테이블에서 Document를 삭제한다.
     * 
     * @param int $document_srl
     */
    public static function deleteDocument(int $document_srl): object
    {
        $args = new stdClass();
        $args->document_srl = $document_srl;
    
        $oDB = DB::getInstance();
        $oDB->begin();
    
        $output = executeQuery('hotoboard.deleteDocument', $args);
        if(!$output->toBool())
        {
            $oDB->rollback();
            throw new \Rhymix\Framework\Exceptions\DBError($output->getMessage());
        }
        $oDB->commit();
    
        return new BaseObject();
    }

     

     

    조언 감사합니다! :D

  • profile
    이거 파이썬으로 만들까 했는데 감사합니다 ㅎ
  • profile profile
    쓸만한 기능 몇개 더 넣었으니 많이 애용해주세요 :D
  • profile
    소스코드로 개인서버에 해봤는데 추가적인 패치하신 부분은 안들어가 있는 것 같더라구요 ㅎㅎ 혹시 이 부분은 제공하실 계획이 없으신걸까요?
  • profile profile

    소스코드 : https://github.com/Waterticket/rx-crud-generator

    제 서버에서 돌리는 코드 전체 업로드하였습니다

    앞으로 자잘한 개선 패치도 올릴 예정이에요

    사용하시다가 뭔가 개선하셨다면 PR 넣어주세요 :D