I used to use $this->log() to log strings, arrays or objects to the debug.log file for inspection with developing and debugging. With CakePHP4, I’m replacing this with Log::debug(). However, if I try to log anything other than a string it throws a strict type error. What’s the recommend approach for logging an array or possibly on object to the debug.log file?
Use Debugger::exportVar
use Cake\Error\Debugger;
$data = [
'a' => [....],
];
Log::debug(Debugger::exportVar($data, 6));
It shows the same output as if you do debug() on cli
I think this is the solution
private function convertToLogMessage(array $msg): string
{
return implode(', ', $msg);
}
Log::info($this->convertToLogMessage($msg))
I hate to revive this issue, but recently ran into another problem that seems odd to me. I started using:
Log::debug(Debugger::exportVar($data, 6));
It was working great at first. I’m not sure if it’s started after updating to 4.1.1 or what. I’ve updated to 4.1.3 with no change.
Any no anytime I use this to try and log something all I get is an output of CSS and HTML. Doesn’t matter what I try to log it just out puts the same thing. I think it’s a error/debugging screen, but don’t understand why it’s outputing that instead of the variable/array/object that I want to log.
2020-08-20 20:21:19 Debug: <style type="text/css">
.cake-debug {
--color-bg: #ECECE9;
--color-highlight-bg: #fcf8e3;
--color-orange: #c44f24;
--color-green: #0b6125;
--color-violet: #a71d5d;
--color-blue: #4070a0;
--color-grey: #5f5f5f;
--color-dark-grey: #222;
--color-cyan: #234aa0;
--color-red: #d33c44;
--indent: 20px;
font-family: monospace;
background: var(--color-bg);
padding: 5px;
line-height: 16px;
font-size: 14px;
margin-bottom: 10px;
}
.cake-debug:last-child {
margin-bottom: 0;
}
.cake-debug > span {
display: block;
margin-bottom: 10px;
color: var(--color-dark-grey);
}
.cake-dbg-object {
display: inline;
}
.cake-dbg-object[data-highlighted=true],
.cake-dbg-object[data-highlighted=true] samp {
background: var(--color-highlight-bg);
}
/*
Array item container and each items are blocks so
nesting works.
*/
.cake-dbg-object-props,
.cake-dbg-array-items {
display: block;
}
.cake-dbg-prop,
.cake-dbg-array-item {
display: block;
padding-left: var(--indent);
min-height: 18px;
}
/** Collapser buttons **/
[data-hidden=true] {
display: none;
}
.cake-dbg-collapse:before {
content: "\25b8";
display: inline-block;
width: 10px;
height: 10px;
font-size: 13px;
line-height: 10px;
background: hsla(0, 0%, 50%, 0.2);
padding: 4px 2px 4px 6px;
border-radius: 3px;
color: var(--color-blue);
}
.cake-dbg-collapse[data-open=true]:before {
content: "\25be";
padding: 4px 3px 4px 5px;
}
/* Textual elements */
.cake-dbg-class {
color: var(--color-cyan);
}
.cake-dbg-property {
color: var(--color-dark-grey);
}
.cake-dbg-visibility {
color: var(--color-violet);
}
.cake-dbg-punct {
color: var(--color-grey);
}
.cake-dbg-string {
color: var(--color-green);
white-space: pre-wrap;
}
.cake-dbg-number {
font-weight: bold;
color: var(--color-blue);
}
.cake-dbg-const {
color: var(--color-yellow);
font-weight: bold;
}
.cake-dbg-ref {
color: var(--color-red);
}
.cake-dbg-special {
color: var(--color-red);
font-style: italic;
}
</style>
<script type="text/javascript">
(function (win, doc) {
function initialize() {
createCollapsibles(doc.querySelectorAll('.cake-dbg-array-items'));
createCollapsibles(doc.querySelectorAll('.cake-dbg-object-props'));
attachRefEvents(doc.querySelectorAll('.cake-dbg'));
openBlocks(doc.querySelectorAll('.cake-debug[data-open-all="true"]'));
}
// Add a name on window so DebugKit can add controls to dump blocks
win.__cakeDebugBlockInit = initialize;
/**
* Open all the collapsed sections in a block.
*/
function openBlocks(blocks) {
blocks.forEach(function (block) {
block.querySelectorAll('.cake-dbg-collapse[data-open="false"]').forEach(function (el) {
el.click();
});
});
}
/**
* Create collapse toggles and attach events
*/
function createCollapsibles(nodes) {
nodes.forEach(function (node) {
// Hide the childnode container if it is not
// a direct parent of the container.
if (!node.parentNode.parentNode.classList.contains('cake-dbg')) {
node.dataset.hidden = true;
}
// Don't show toggles for empty arrays/objects
if (node.childNodes.length == 0) {
return;
}
var collapser = doc.createElement('a');
collapser.classList.add('cake-dbg-collapse');
collapser.dataset.open = !node.dataset.hidden;
collapser.setAttribute('href', '#')
collapser.setAttribute('title', 'Toggle items');
// Add open/close behavior
collapser.addEventListener('click', function (event) {
event.preventDefault();
event.stopPropagation();
node.dataset.hidden = node.dataset.hidden === 'true' ? 'false' : 'true';
collapser.dataset.open = collapser.dataset.open === 'true' ? 'false' : 'true';
});
node.parentNode.insertBefore(collapser, node);
});
}
/**
* When ref links are clicked open the path to that
* element and highlight the reference
*/
function attachRefEvents(nodes) {
nodes.forEach(function (container) {
var refLinks = container.querySelectorAll('.cake-dbg-ref');
refLinks.forEach(function (ref) {
ref.addEventListener('click', function (event) {
event.preventDefault();
event.stopPropagation();
var target = document.getElementById(ref.getAttribute('href').substr(1));
openPath(container, target);
});
});
});
}
function openPath(container, target) {
// Open the target element
var expander = target.querySelector('.cake-dbg-collapse');
if (expander.dataset.open === 'false') {
expander.click();
}
container.querySelectorAll('.cake-dbg-object').forEach(function (el) {
el.dataset.highlighted = 'false';
})
target.dataset.highlighted = 'true';
var current = target;
// Traverse up the tree opening all closed containers.
while (true) {
var parent = current.parentNode;
if (parent == container) {
break;
}
if (parent.classList.contains('cake-dbg-object') || parent.classList.contains('cake-dbg-array')) {
expander = parent.querySelector('.cake-dbg-collapse');
if (expander.dataset.open === 'false') {
expander.click();
}
}
current = parent;
}
}
doc.addEventListener('DOMContentLoaded', initialize);
}(window, document))
</script>
<div class="cake-dbg"><span class="cake-dbg-object" id="cake-db-object-5f3edb3fe8c552.33406134-0"><span class="cake-dbg-punct">object(</span><span class="cake-dbg-class">App\Model\Entity\Setting</span><span class="cake-dbg-punct">) id:</span><span class="cake-dbg-number">0</span><span class="cake-dbg-punct"> {</span><samp class="cake-dbg-object-props"><span class="cake-dbg-prop"><span class="cake-dbg-property">'key2'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-string">'sdfsdfsdf'</span></span><span class="cake-dbg-prop"><span class="cake-dbg-property">'value2'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-string">'sdfsdfsdf'</span></span><span class="cake-dbg-prop"><span class="cake-dbg-property">'[new]'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-const">true</span></span><span class="cake-dbg-prop"><span class="cake-dbg-property">'[accessible]'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-array"><span class="cake-dbg-punct">[</span><samp class="cake-dbg-array-items"><span class="cake-dbg-array-item"><span class="cake-dbg-string">'key2'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-const">true</span><span class="cake-dbg-punct">,</span></span><span class="cake-dbg-array-item"><span class="cake-dbg-string">'value2'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-const">true</span><span class="cake-dbg-punct">,</span></span></samp><span class="cake-dbg-punct">]</span></span></span><span class="cake-dbg-prop"><span class="cake-dbg-property">'[dirty]'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-array"><span class="cake-dbg-punct">[</span><samp class="cake-dbg-array-items"><span class="cake-dbg-array-item"><span class="cake-dbg-string">'key2'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-const">true</span><span class="cake-dbg-punct">,</span></span><span class="cake-dbg-array-item"><span class="cake-dbg-string">'value2'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-const">true</span><span class="cake-dbg-punct">,</span></span></samp><span class="cake-dbg-punct">]</span></span></span><span class="cake-dbg-prop"><span class="cake-dbg-property">'[original]'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-array"><span class="cake-dbg-punct">[</span><samp class="cake-dbg-array-items"></samp><span class="cake-dbg-punct">]</span></span></span><span class="cake-dbg-prop"><span class="cake-dbg-property">'[virtual]'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-array"><span class="cake-dbg-punct">[</span><samp class="cake-dbg-array-items"></samp><span class="cake-dbg-punct">]</span></span></span><span class="cake-dbg-prop"><span class="cake-dbg-property">'[hasErrors]'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-const">false</span></span><span class="cake-dbg-prop"><span class="cake-dbg-property">'[errors]'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-array"><span class="cake-dbg-punct">[</span><samp class="cake-dbg-array-items"></samp><span class="cake-dbg-punct">]</span></span></span><span class="cake-dbg-prop"><span class="cake-dbg-property">'[invalid]'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-array"><span class="cake-dbg-punct">[</span><samp class="cake-dbg-array-items"></samp><span class="cake-dbg-punct">]</span></span></span><span class="cake-dbg-prop"><span class="cake-dbg-property">'[repository]'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-string">'Settings'</span></span><span class="cake-dbg-prop"><span class="cake-dbg-visibility">protected</span> <span class="cake-dbg-property">_accessible</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-array"><span class="cake-dbg-punct">[</span><samp class="cake-dbg-array-items"><span class="cake-dbg-array-item"><span class="cake-dbg-string">'key2'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-const">true</span><span class="cake-dbg-punct">,</span></span><span class="cake-dbg-array-item"><span class="cake-dbg-string">'value2'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-const">true</span><span class="cake-dbg-punct">,</span></span></samp><span class="cake-dbg-punct">]</span></span></span><span class="cake-dbg-prop"><span class="cake-dbg-visibility">protected</span> <span class="cake-dbg-property">_fields</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-array"><span class="cake-dbg-punct">[</span><samp class="cake-dbg-array-items"><span class="cake-dbg-array-item"><span class="cake-dbg-string">'key2'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-string">'sdfsdfsdf'</span><span class="cake-dbg-punct">,</span></span><span class="cake-dbg-array-item"><span class="cake-dbg-string">'value2'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-string">'sdfsdfsdf'</span><span class="cake-dbg-punct">,</span></span></samp><span class="cake-dbg-punct">]</span></span></span><span class="cake-dbg-prop"><span class="cake-dbg-visibility">protected</span> <span class="cake-dbg-property">_original</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-array"><span class="cake-dbg-punct">[</span><samp class="cake-dbg-array-items"></samp><span class="cake-dbg-punct">]</span></span></span><span class="cake-dbg-prop"><span class="cake-dbg-visibility">protected</span> <span class="cake-dbg-property">_hidden</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-array"><span class="cake-dbg-punct">[</span><samp class="cake-dbg-array-items"></samp><span class="cake-dbg-punct">]</span></span></span><span class="cake-dbg-prop"><span class="cake-dbg-visibility">protected</span> <span class="cake-dbg-property">_virtual</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-array"><span class="cake-dbg-punct">[</span><samp class="cake-dbg-array-items"></samp><span class="cake-dbg-punct">]</span></span></span><span class="cake-dbg-prop"><span class="cake-dbg-visibility">protected</span> <span class="cake-dbg-property">_dirty</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-array"><span class="cake-dbg-punct">[</span><samp class="cake-dbg-array-items"><span class="cake-dbg-array-item"><span class="cake-dbg-string">'key2'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-const">true</span><span class="cake-dbg-punct">,</span></span><span class="cake-dbg-array-item"><span class="cake-dbg-string">'value2'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-const">true</span><span class="cake-dbg-punct">,</span></span></samp><span class="cake-dbg-punct">]</span></span></span><span class="cake-dbg-prop"><span class="cake-dbg-visibility">protected</span> <span class="cake-dbg-property">_accessors</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-array"><span class="cake-dbg-punct">[</span><samp class="cake-dbg-array-items"><span class="cake-dbg-array-item"><span class="cake-dbg-string">'App\Model\Entity\Setting'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-array"><span class="cake-dbg-punct">[</span><samp class="cake-dbg-array-items"><span class="cake-dbg-array-item"><span class="cake-dbg-string">'get'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-array"><span class="cake-dbg-punct">[</span><samp class="cake-dbg-array-items"><span class="cake-dbg-array-item"><span class="cake-dbg-string">'key2'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-string">''</span><span class="cake-dbg-punct">,</span></span><span class="cake-dbg-array-item"><span class="cake-dbg-string">'value2'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-string">''</span><span class="cake-dbg-punct">,</span></span></samp><span class="cake-dbg-punct">]</span></span><span class="cake-dbg-punct">,</span></span><span class="cake-dbg-array-item"><span class="cake-dbg-string">'set'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-array"><span class="cake-dbg-punct">[</span><samp class="cake-dbg-array-items"><span class="cake-dbg-array-item"><span class="cake-dbg-string">'key2'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-string">''</span><span class="cake-dbg-punct">,</span></span><span class="cake-dbg-array-item"><span class="cake-dbg-string">'value2'</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-string">''</span><span class="cake-dbg-punct">,</span></span></samp><span class="cake-dbg-punct">]</span></span><span class="cake-dbg-punct">,</span></span></samp><span class="cake-dbg-punct">]</span></span><span class="cake-dbg-punct">,</span></span></samp><span class="cake-dbg-punct">]</span></span></span><span class="cake-dbg-prop"><span class="cake-dbg-visibility">protected</span> <span class="cake-dbg-property">_new</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-const">true</span></span><span class="cake-dbg-prop"><span class="cake-dbg-visibility">protected</span> <span class="cake-dbg-property">_errors</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-array"><span class="cake-dbg-punct">[</span><samp class="cake-dbg-array-items"></samp><span class="cake-dbg-punct">]</span></span></span><span class="cake-dbg-prop"><span class="cake-dbg-visibility">protected</span> <span class="cake-dbg-property">_invalid</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-array"><span class="cake-dbg-punct">[</span><samp class="cake-dbg-array-items"></samp><span class="cake-dbg-punct">]</span></span></span><span class="cake-dbg-prop"><span class="cake-dbg-visibility">protected</span> <span class="cake-dbg-property">_registryAlias</span><span class="cake-dbg-punct"> => </span><span class="cake-dbg-string">'Settings'</span></span></samp><span class="cake-dbg-punct">}</span></span></div>
I don’t use Cake 4 yet.
The HTML Output is added in PR #14209
Try calling with this
$oldFormatter = Log::configInstance('exportFormatter');
Log::configInstance('exportFormatter', Cake\Error\Debug\TextFormatter::class);
Log::debug(Debugger::exportVar($data, 6));
Log::configInstance('exportFormatter', $oldFormatter);
This might be worthy of opening an issue to request a method that forces the use of TextFormatter
Checking the Debugger
class I see there is a method log
Try use that for example
I think you had a few errors in your code. After fixing that it does appear to work. Here’s the code:
$oldFormatter = Debugger::configInstance('exportFormatter');
Debugger::configInstance('exportFormatter', TextFormatter::class);
Log::debug(Debugger::exportVar($test, 6));
Debugger::configInstance('exportFormatter', $oldFormatter);
Thanks for the help on this. As someone moving from CakePHP 2, this simple task has been a headache. Do you think this is worthy of an issue request? If so I’ll create one. I know there is the LogTrait, but it doesn’t work like it did in CakePHP2 (it won’t accept objects or arrays). For an easier transition I wonder if making it work like it did with version 2 would be better. I’m not sure what version 3 does.
If this code
Debugger::log($test, 'debug', 6);
Writes html in the log file, then yes I would open an issue.
If not then I would just define a function like log()
thas does the code I posted.