### First-time setup commands Source: https://github.com/vrana/adminer/blob/main/CLAUDE.md Run these commands once after cloning the repository to initialize submodules and install PHP and npm dependencies. ```bash git submodule update --init --recursive # Initialize submodules (adminer/static/jush, conf/JsShrink, conf/PhpShrink) composer install # Does the same through the `submodules` script, plus PHPCS, PHPStan and the npm packages needed by ESLint ``` -------------------------------- ### Create/edit index.php to enable plugins and password-less login Source: https://github.com/vrana/adminer/wiki/Enable-sqlite3 Full index.php example that includes the plugin loader, enables the AdminerLoginPasswordLess plugin with the specified username and password hash, and includes the original Adminer. The AdminerLoginServers plugin is commented out. ```php filter_input(INPUT_SERVER, 'SERVER_NAME') // ]), // allow sqlite with login-password-less plugin and selecting sqlite3 server type and put full path to sqlite database file in database field. new AdminerLoginPasswordLess("sladmin", password_hash("mypassword", PASSWORD_DEFAULT)), ]; return new AdminerPlugin($plugins); } // Include original Adminer or Adminer Editor. include "./adminer.php"; ``` -------------------------------- ### Start development server Source: https://github.com/vrana/adminer/blob/main/CLAUDE.md Starts the built-in PHP development server. Browse to http://127.0.0.1:8000/adminer/ for the dev version. ```bash php -S 127.0.0.1:8000 ``` -------------------------------- ### Start development server with Xdebug coverage Source: https://github.com/vrana/adminer/blob/main/docs/developing.md Start the development server with Xdebug coverage mode enabled and OPcache disabled. Required for collecting code coverage; without it, the coverage page refuses to start a new coverage session. ```bash php -d xdebug.mode=coverage -d opcache.enable=0 -S 127.0.0.1:8000 ``` -------------------------------- ### Customize record limit with selectLimitProcess() and selectLimitPrint() Source: https://github.com/vrana/adminer/wiki/Technical-Wiki Override selectLimitProcess() to set the default limit and selectLimitPrint() to render the limit selector. The example uses a default of 20 with options 20, 50, and 100. ```php function selectLimitProcess() { return (isset($_GET["limit"]) ? $_GET["limit"] : "20"); } function selectLimitPrint($limit) { echo "
" . lang('Limit') . "
"; //
for easy styling echo html_select("limit", array("", "20", "50", "100"), $limit); echo "
\n"; } ``` -------------------------------- ### Create OpenSearch user with superuser role Source: https://github.com/vrana/adminer/blob/main/tests/README.md Creates an OpenSearch user with superuser role for servers that require a password, as the default test setup uses no security plugin. ```sh curl -u elastic:PASSWORD -X POST https://localhost:9200/_security/user/ODBC \ -H 'Content-Type: application/json' -d '{"password": "ODBC12", "roles": ["superuser"]}' ``` -------------------------------- ### Adminer style vs isset, ??, and idx() for array key checks Source: https://github.com/vrana/adminer/blob/main/docs/developing.md Four equivalent ways to check a GET parameter, contrasting Adminer's style (relying on default uninitialized array values) with explicit isset, null coalescing (PHP 7.0+), and the idx() helper. Adminer silences undefined array key errors but still reports undefined variables and null offsets. ```php if (extension_loaded("mysqli") && $_GET["ext"] != "pdo") ``` ```php if (extension_loaded("mysqli") && (!isset($_GET["ext"]) || $_GET["ext"] != "pdo")) ``` ```php if (extension_loaded("mysqli") && ($_GET["ext"] ?? "") != "pdo") ``` ```php if (extension_loaded("mysqli") && idx($_GET, "ext") != "pdo") ``` -------------------------------- ### Adminer selectLink function to link ORID field to external file Source: https://github.com/vrana/adminer/wiki/Technical-Wiki Use this function in an Adminer plugin to turn the ORID field value in the chq_batches table into a link to an external file (orslip.php) with the value passed as the 'orid' GET parameter. The link is only generated when the field is ORID, the select is chq_batches, and the value is not NULL. ```php function selectLink($val, $field) { if ($field['field'] == 'ORID' && $_GET['select'] == 'chq_batches' && $val !== NULL) return 'orslip.php?select=chq_batches&orid='.$val; } ``` -------------------------------- ### Set up MS SQL test database and login Source: https://github.com/vrana/adminer/blob/main/tests/README.md Sets up the MS SQL test database and login. The database must exist before the run because the login cannot create it; the password policy is disabled because 'ODBC' does not satisfy it. ```sql CREATE DATABASE adminer_test; CREATE LOGIN ODBC WITH PASSWORD = 'ODBC', DEFAULT_DATABASE = adminer_test, CHECK_POLICY = OFF; USE adminer_test; CREATE USER ODBC FOR LOGIN ODBC; ALTER ROLE db_owner ADD MEMBER ODBC; ``` -------------------------------- ### Build commands (composer compile and php compile.php) Source: https://github.com/vrana/adminer/blob/main/CLAUDE.md Compile the single-file distribution. The first command builds all drivers and languages; the others show how to limit the build to specific drivers and languages, and how to build Adminer Editor. ```bash composer compile # All drivers, all languages → adminer.php php compile.php mysql # MySQL driver only php compile.php mysql en # MySQL + English only php compile.php editor mysql # Adminer Editor with MySQL ``` -------------------------------- ### Create and populate adminer_demo database Source: https://github.com/vrana/adminer/blob/main/tests/README.md Creates the adminer_demo database and populates it from the demo.adminer.org deployment's mysql.sql file. Used by screenshots.spec.js to set up the database for screenshots. ```sh mysql -e "CREATE DATABASE adminer_demo" mysql adminer_demo < ../adminer-demo/mysql.sql ``` -------------------------------- ### Create CockroachDB user with CREATEDB Source: https://github.com/vrana/adminer/blob/main/tests/README.md Creates a CockroachDB user named ODBC and grants CREATEDB. Run these via `cockroach sql --insecure --host=localhost:26257`. ```sql CREATE USER "ODBC"; ALTER USER "ODBC" CREATEDB; ``` -------------------------------- ### Create restricted MySQL user for screenshots Source: https://github.com/vrana/adminer/blob/main/tests/README.md Creates a MySQL user 'adminer' with password 'adminer' and grants all privileges on the adminer_demo database only. This restricts the user's access so the server overview doesn't list other databases. ```sql CREATE USER 'adminer'@'localhost' IDENTIFIED BY 'adminer'; GRANT ALL PRIVILEGES ON adminer_demo.* TO 'adminer'@'localhost'; ``` -------------------------------- ### Compile Adminer for PostgreSQL and Russian Source: https://github.com/vrana/adminer/wiki/Compile-adminer-from-sources Run the compile.php script with the pgsql and ru arguments to compile Adminer for PostgreSQL and Russian language. Requires PHP 7.4. ```bash # only for PostgreSQL and Russian language /usr/bin/php7.4 compile.php pgsql ru ``` -------------------------------- ### Code quality commands (composer check, phpcs, phpstan) Source: https://github.com/vrana/adminer/blob/main/CLAUDE.md Run code quality checks. The first command runs all three tools; the others run PHPCS and PHPStan individually with the project's configuration. ```bash composer check # Runs phpcs + phpstan + eslint vendor/bin/phpcs --standard=conf/phpcs.xml # PHP code style (PSR-12 based, tab-indented) vendor/bin/phpstan analyse -c conf/phpstan.neon # Static analysis (level 6) ``` -------------------------------- ### Create ODBC user and grant privileges for MySQL tests Source: https://github.com/vrana/adminer/blob/main/tests/README.md Creates the ODBC user with password ODBC and grants all privileges with grant option, as required by the MySQL tests. The tests log in as ODBC and expect the server to reject a wrong password. ```sql CREATE USER 'ODBC'@'localhost' IDENTIFIED BY 'ODBC'; GRANT ALL PRIVILEGES ON *.* TO 'ODBC'@'localhost' WITH GRANT OPTION; ``` -------------------------------- ### Create PostgreSQL role for tests Source: https://github.com/vrana/adminer/blob/main/tests/README.md Creates a PostgreSQL role named ODBC with login and CREATEDB privileges. The role name must be quoted because PostgreSQL preserves the case as written. ```sql CREATE ROLE "ODBC" LOGIN PASSWORD 'ODBC' CREATEDB; ``` -------------------------------- ### Compile Adminer for MySQL and Russian Source: https://github.com/vrana/adminer/wiki/Compile-adminer-from-sources Run the compile.php script with the mysql and ru arguments to compile Adminer for MySQL and Russian language. Requires PHP 7.4. ```bash # only for MySQL and Russian language /usr/bin/php7.4 compile.php mysql ru ``` -------------------------------- ### Comment out AdminerLoginServers in index.php Source: https://github.com/vrana/adminer/wiki/Enable-sqlite3 Comment out the AdminerLoginServers plugin if present in index.php to allow the login form to show the System field. ```php // new AdminerLoginServers([ // filter_input(INPUT_SERVER, 'HTTP_HOST') => filter_input(INPUT_SERVER, 'SERVER_NAME') // ]), ``` -------------------------------- ### Ternary vs if/else for title assignment Source: https://github.com/vrana/adminer/blob/main/docs/developing.md Shows the preferred ternary style versus the less desirable if/else alternative for setting a title. The comment warns that changing else to elseif could leave $title uninitialized. ```php // Preferred $title = ($update ? lang('Save and continue editing') : lang('Save and insert next') ); ``` ```php // Less desirable if ($update) { $title = lang('Save and continue editing'); } else { // If you change else to elseif in the future then $title may stay uninitialized $title = lang('Save and insert next'); } ``` -------------------------------- ### Add plugin to Adminer with compile.sh Source: https://github.com/vrana/adminer/wiki/Compile-Adminer-with-Plugin(s)-and-Design Part of compile.sh that downloads a plugin and appends the necessary PHP code to bootstrap.inc.php to embed the plugin. The PHP code includes the plugin files and defines adminer_object() to register the plugin. ```bash echo -e "\n$step. Load plugin's sources:\n" ((step+=1)) wget -P adminer/plugins/ https://raw.githubusercontent.com/.../master/my-plugin.php echo -e "\n$step. Adding the plugin to the sources\n" ((step+=1)) cat << "EOPHP" >> adminer/adminer/include/bootstrap.inc.php include "../plugins/plugin.php"; // needed to add plugin(s) to Adminer include "../plugins/my-plugin.php"; function adminer_object() { $plugins = array(new MyPluginClasse()); return new AdminerPlugin($plugins); } EOPHP ``` -------------------------------- ### Limit displayed tables with tableName() Source: https://github.com/vrana/adminer/wiki/Technical-Wiki Override tableName() to show only tables in the allowed list. Tables without comments return an empty string and are ignored by Adminer. ```php function tableName($tableStatus) { // tables without comments would return empty string and will be ignored by Adminer $allowed_tables = Array('mytable1', 'mytable2'); if (in_array($tableStatus["Name"], $allowed_tables)) return h($tableStatus["Comment"]); else return ''; } ``` -------------------------------- ### Create Oracle user with DBA privileges Source: https://github.com/vrana/adminer/blob/main/tests/README.md Creates an Oracle user with DBA privileges, required for the tests to drop and recreate the adminer_test schema through Adminer. ```sql CREATE USER ODBC IDENTIFIED BY ODBC; GRANT DBA TO ODBC; ``` -------------------------------- ### Register event handler with on() and data-onclick attribute Source: https://github.com/vrana/adminer/blob/main/docs/developing.md The PHP `on()` helper prints a `data-on` attribute on an element, and the resulting HTML shows the attribute that `delegateEvent()` parses. The handler is called with the arguments from the attribute followed by the event. ```php echo "" . lang('Warnings') . ""; ``` ```html Warnings ``` -------------------------------- ### Add Adminer design with compile.sh Source: https://github.com/vrana/adminer/wiki/Compile-Adminer-with-Plugin(s)-and-Design Part of compile.sh that embeds a design by appending the design's adminer.css to the main CSS file. It backs up the original CSS file before concatenating. ```bash design=$2 echo -e "\n$step. Set the design: $design\n" ((step+=1)) cp $CSS_FILE $CSS_FILE.backup cat $CSS_FILE.backup $DESIGNS_DIR/$design/adminer.css > $CSS_FILE ``` -------------------------------- ### Choose binary vs string literal with is_blob() and is_utf8() Source: https://github.com/vrana/adminer/blob/main/docs/developing.md Use this expression to decide between a binary literal and a string literal when building a condition. It checks both the column type and the value: only when the column is binary (is_blob) and the value is not printable text (is_utf8) does it call quoteBinary(); otherwise it uses q(). Never decide by the value alone, because a binary literal is not a drop-in replacement for a string literal in PostgreSQL or MySQL. ```php is_blob($field) && !is_utf8($val) ? driver()->quoteBinary($val) : q($val) ``` -------------------------------- ### Clean compiled files Source: https://github.com/vrana/adminer/blob/main/CLAUDE.md Removes all compiled adminer*.php and editor*.php files. ```bash composer clean # Remove all compiled adminer*.php and editor*.php ``` -------------------------------- ### Customize column display with fieldName() Source: https://github.com/vrana/adminer/wiki/Technical-Wiki Override fieldName() to control which columns appear in table listings and selects. Hides hash fields, shows commented columns, and includes specific fields or labels. ```php function fieldName($field, $order = 0) { /* $field = Array ( [field] => stock_id [full_type] => varchar(20) [type] => varchar [length] => 20 [unsigned] => [default] => [null] => [auto_increment] => [on_update] => [collation] => utf8_general_ci [privileges] => Array ( [select] => 0 [insert] => 1 [update] => 2 [references] => 3 ) [comment] => Part# [primary] => 1 ) */ if ($order && preg_match('~_(md5|sha1)$~', $field["field"])) { return ""; // hide hashes in select } // display only column with comments, first two of them plus searched columns and specific columns if ($order < 2) { return h($field["comment"]); } else if ($order) { if (preg_match('~^(ItemDesc|category_id|UPC)$~', $field["field"])) { return h($field["comment"]); // chosen fields ItemDesc,category_id,UPC in select } if (preg_match('~(Price)$~', $field["field"])) { return h($field["comment"]); // chosen field names in select ending with Price } if (preg_match('~^(Product#)$~', $field["comment"])) { return h($field["comment"]); // chosen field label Product# in select } } foreach ((array) $_GET["where"] as $key => $where) { if ($where["col"] == $field["field"] && ($key >= 0 || $where["val"] != "")) { return h($field["comment"]); } } return ""; } ``` -------------------------------- ### Adminer viewonly patch for functions.inc.php and select.inc.php Source: https://github.com/vrana/adminer/wiki/Technical-Wiki Patch for Adminer that adds a read-only 'view' mode. It disables form fields and hides save/delete buttons when 'viewonly' is set, and adds a 'view' link next to the edit link in the select list. ```diff --- adminer/include/functions.inc.php Mon Jan 25 04:02:41 2016 +++ adminer/include/functions.inc.php Tue Feb 02 12:34:43 2016 @@ -864,6 +864,7 @@ } $functions = (isset($_GET["select"]) || $reset ? array("orig" => lang('original')) : array()) + $adminer->editFunctions($field); $attrs = " name='fields[$name]'"; + $attrs .= isset($_GET['viewonly']) ? " disabled='true'" : ""; if ($field["type"] == "enum") { echo nbsp($functions[""]) . "" . $adminer->editInput($_GET["edit"], $field, $attrs, $value); } else { @@ -1369,20 +1370,22 @@ echo "\n"; } echo "

\n"; - if ($fields) { - echo "\n"; - if (!isset($_GET["select"])) { - echo "\n"; + if (!isset($_GET['viewonly'])) { + if ($fields) { + echo "\n"; + if (!isset($_GET["select"])) { + echo "\n"; + } + } + echo ($update ? "\n" + : ($_POST || !$fields ? "" : "\n") + ); + if (isset($_GET["select"])) { + hidden_fields(array("check" => (array) $_POST["check"], "clone" => $_POST["clone"], "all" => $_POST["all"])); } } - echo ($update ? "\n" - : ($_POST || !$fields ? "" : "\n") - ); - if (isset($_GET["select"])) { - hidden_fields(array("check" => (array) $_POST["check"], "clone" => $_POST["clone"], "all" => $_POST["all"])); } ?> "> --- adminer/select.inc.php Mon Jan 25 04:02:41 2016 +++ adminer/select.inc.php Tue Feb 02 14:17:32 2016 @@ -366,7 +366,10 @@ } $unique_idf .= "&" . ($val !== null ? urlencode("where[" . bracket_escape($key) . "]") . "=" . urlencode($val) : "null%5B%5D=" . urlencode($key)); } - echo "" . (!$group && $select ? "" : "" . checkbox("check[]", substr($unique_idf, 1), in_array(substr($unique_idf, 1), (array) $_POST["check"]), "", "this.form['all'].checked = false; formUncheck('all-page');") . ($is_group || information_schema(DB) ? "" : " " . lang('edit') . "")); + $edit_link_part = " " . lang('edit') . ""; + $view_link_part = " | " . lang('view') . ""; + + echo "" . (!$group && $select ? "" : "" . checkbox("check[]", substr($unique_idf, 1), in_array(substr($unique_idf, 1), (array) $_POST["check"]), "", "this.form['all'].checked = false; formUncheck('all-page');") . ($is_group || information_schema(DB) ? "" : $edit_link_part . $view_link_part)); foreach ($row as $key => $val) { if (isset($names[$key])) { ``` -------------------------------- ### Hide auto-increment primary key in Adminer new record form Source: https://github.com/vrana/adminer/wiki/Technical-Wiki Overrides the fieldName function to hide auto-increment primary key fields during insert. Populate the $hidePKfields array with table and field names as needed; the function also hides hash fields and limits displayed comments. ```php function fieldName($field, $order = 0) { if ($order && preg_match('~_(md5|sha1)$~', $field["field"])) { return ""; // hide hashes in select } // Hide AutoInc Primary keys during Insert if (isset($_GET['edit'])) { $hidePKfields = Array( Array('htable' => 'employees', 'hfield' => 'EmployeeID') , Array('htable' => 'leaves', 'hfield' => 'LeaveID') ); foreach ($hidePKfields as $val) { if ($_GET['edit'] == $val['htable'] && $field['field'] == $val['hfield'] && !isset($_GET['where'][$val['hfield']])) return ""; } } // display only column with comments, first 60 of them plus searched columns if ($order < 60) { return h($field["comment"]); } foreach ((array) $_GET["where"] as $key => $where) { if ($where["col"] == $field["field"] && ($key >= 0 || $where["val"] != "")) { return h($field["comment"]); } } return ""; } ``` -------------------------------- ### Replace JOIN condition in mssql.inc.php to support UDDT Source: https://github.com/vrana/adminer/wiki/MSSQL-Driver In Adminer 4.7.7, modify line #375 in mssql.inc.php to change the JOIN condition from using c.user_type_id to c.system_type_id. This enables support for user-defined data types (UDDT). ```diff -- JOIN sys.types t ON c.user_type_id = t.user_type_id ++ JOIN sys.types t ON c.**system**_type_id = t.user_type_id ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.