Разрешаем подчеркивания

Очень много разработчиков сталкиваются с проблемой при использовании RedBeanPHP, когда PHP выдает ошибку:

Fatal error: Uncaught RedBeanPHP\RedException: Invalid type
Внимание! В RedBean нельзя по умолчанию использовать подчеркивания в названиях таблиц Баз Данных, т.е. в этой библиотеке подчеркивания нужны для обозначения отношений двух таблиц.

Но разрешить работу с таблицами, в названии которых есть нижнее подчеркивание все-таки можно, так как многие фреймворки и CMS имеют в именах таблиц префиксы. Это касается, кстати и WordPress в которой для названий используется префикс wp_.

Изначально RedBean не понимает, вернее не разрешает использование _ подчеркиваний.

Как обойти эту проверку?

Для решения задачи нам нужно написать небольшой плагин (фрагмент кода):

R::ext('xdispense', function($table_name){
return R::getRedBean()->dispense($table_name);
});

И потом создаем таблицу через xdispense:

$note = R::xdispense('lead_notes');

Решение найдено на stackoverflow.com и потом я нашел решение на официальном сайте RedBeanPHP по этой ссылке.

На официальном сайте есть следующее объяснение:

В RedBeanPHP символ подчеркивания ‘_’ используется для обозначения отношения между двумя таблицами. Например, таблица book_tag используется для связывания книг с тегами.

Итак, если вы хотите использовать префиксы таблиц, такие как cms_ или tbl_, вам придется обойти проверку политики схемы RedBeanPHP следующим образом:

R::ext('xdispense', function( $type ){ 
        return R::getRedBean()->dispense( $type ); 
    });

Теперь вы можете использовать подчеркивание в вашем типе (type) bean-компонента:

$page = R::xdispense( 'cms_page' );

Однако название типа все равно выглядит странно. Используя константу, вы можете улучшить читаемость этого кода:

define( 'PAGE', 'cms_page' );
$page = R::xdispense( PAGE );

Это также работает для отношений:

define( 'PAGES', 'ownCms_page' );
$pages = $site->{PAGES};

Вот полный пример:

    //Define your mappings like this
    define( 'POEM', 'tbl_poem' );
    define( 'BOOK', 'tbl_book' );
    define( 'AUTHOR', 'tbl_author' );
    define( 'CATEGORY', 'tbl_category' );
    define( 'POEMS', 'ownTblPoem' );
    define( 'CATEGORIES', 'sharedTblCategory' );

    //Create an extension to by-pass security check in R::dispense
    R::ext('xdispense', function( $type ){
        return R::getRedBean()->dispense( $type );
    });

    //Use tbl_book_category instead of tbl_book_tbl_category
    R::renameAssociation([
        'tbl_book_tbl_category' => 'tbl_book_category' 
    ]);

    //Use them like this:
    $poem = R::xdispense( POEM );
    $poem->title = 'Trees';
    $author = R::xdispense( AUTHOR );
    $author->name = 'Joyce Kilmer';
    $book = R::xdispense( BOOK );
    $book->title = 'Trees and other poems';
    $category = R::xdispense( CATEGORY );
    $category->name = 'nature';
    $book->{AUTHOR} = $author;
    $book->{POEMS}[] = $poem;
    $book->{CATEGORIES}[] = $category;
    $id = R::store( $book );

    //For testing purposes let's output something:
    $book = R::load( BOOK, $id );
    $poem = reset( $book->{POEMS} );
    $author = $book->{AUTHOR};
    $category = reset( $book->{CATEGORIES} );

    echo "Have you ever read '{$poem->title}' ({$book->title}) by {$author->name} ?
    it's a beautiful poem about {$category->name}.";

Этот код выведет:

Have you ever read ‘Trees’ (Trees and other poems) by Joyce Kilmer ? it’s a beautiful poem about nature.

Была ли эта страница полезной?