13 KiB
🛠️ MANUALE TECNICO NETGESCON - RISOLUZIONE PROBLEMI E BEST PRACTICES
Data Aggiornamento: 21 Luglio 2025
Versione: 2.1.0
Autore: GitHub Copilot + Team NetGescon
📋 INDICE RAPIDO
- Problemi Risolti Oggi
- Errori Comuni e Soluzioni
- Best Practices Blade Templates
- Sistema Tab Unificato
- Gestione Relazioni Database
- Debug e Testing
- Checklist Pre-Deploy
❌ PROBLEMI RISOLTI OGGI
1. Errore Sintassi PHP - Carattere Unicode
ERRORE: syntax error, unexpected identifier "×", expecting ")"
FILE: resources/views/admin/stabili/show.blade.php :169
CAUSA: Uso di carattere moltiplicazione Unicode × invece dell'operatore PHP *
SOLUZIONE:
// ❌ ERRATO
{{ ($palazzina->numero_scale ?? 1) × ($palazzina->numero_piani ?? 3) }}
// ✅ CORRETTO
{{ ($palazzina->numero_scale ?? 1) * ($palazzina->numero_piani ?? 3) }}
PREVENZIONE: Usare sempre operatori PHP standard, non caratteri speciali Unicode
2. Errore Relazioni Null
ERRORE: Call to a member function count() on null
FILE: resources/views/admin/stabili/show.blade.php :121
CAUSA: Chiamata metodi su relazioni non caricate o null
SOLUZIONE:
// ❌ ERRATO - Può causare errore se relazione è null
{{ $stabile->palazzine->count() }}
// ✅ CORRETTO - Usa nullsafe operator
{{ $stabile->palazzine?->count() ?? 0 }}
// ✅ ALTERNATIVA - Verifica esistenza
{{ ($stabile->palazzine && $stabile->palazzine->count()) ? $stabile->palazzine->count() : 0 }}
PREVENZIONE: Usare sempre ?-> per relazioni che potrebbero essere null
3. Rotte Non Definite
ERRORE: Route [admin.unita_immobiliari.index] not defined
FILE: resources/views/admin/stabili/tabs/dati-generali.blade.php :214
CAUSA: Riferimento a rotte non esistenti nel sistema di routing
SOLUZIONE:
// ✅ Verifica esistenza rotta prima di usarla
@if(Route::has('admin.unita_immobiliari.index'))
<a href="{{ route('admin.unita_immobiliari.index') }}">
@else
<a href="#" onclick="alert('Funzionalità in sviluppo')">
@endif
4. Metodi Controller Mancanti
ERRORE: Method App\Http\Controllers\Admin\StabileController::authorize does not exist
FILE: app/Http/Controllers/Admin/StabileController.php :76
CAUSA: Chiamata a metodi non implementati nel controller
SOLUZIONE: Implementare il metodo o rimuovere la chiamata
🔧 ERRORI COMUNI E SOLUZIONI
A. Errori Blade Template
1. Variabili Non Definite
// ❌ ERRATO
{{ $variabile->proprieta }}
// ✅ CORRETTO
{{ $variabile->proprieta ?? 'Valore Default' }}
{{ isset($variabile) ? $variabile->proprieta : 'Default' }}
2. Include Files Mancanti
// ❌ ERRATO
@include('admin.stabili.tabs.non-esistente')
// ✅ CORRETTO - Verifica esistenza
@if(view()->exists('admin.stabili.tabs.tab-name'))
@include('admin.stabili.tabs.tab-name')
@else
<p>Contenuto in sviluppo</p>
@endif
3. Loop su Collezioni Null
// ❌ ERRATO
@foreach($stabile->palazzine as $palazzina)
// ✅ CORRETTO
@forelse($stabile->palazzine ?? [] as $palazzina)
// Contenuto
@empty
<p>Nessun elemento trovato</p>
@endforelse
B. Errori JavaScript
1. Selezione Elementi DOM
// ❌ ERRATO - Può essere null
const element = document.getElementById('tab-content');
element.classList.add('active');
// ✅ CORRETTO - Verifica esistenza
const element = document.getElementById('tab-content');
if (element) {
element.classList.add('active');
}
2. Event Listeners
// ✅ BEST PRACTICE - Usa delegazione eventi
document.addEventListener('DOMContentLoaded', function() {
// Inizializzazione sicura
const buttons = document.querySelectorAll('.netgescon-tab-btn');
buttons.forEach(button => {
if (button) {
button.addEventListener('click', handleTabClick);
}
});
});
🎨 BEST PRACTICES BLADE TEMPLATES
1. Struttura Standardizzata Tab
<!-- Tab Navigation -->
<nav class="-mb-px flex space-x-8" aria-label="Tabs" role="tablist">
<button class="netgescon-tab-btn active"
data-tab="nome-tab"
type="button"
role="tab">
<i class="fas fa-icon mr-2"></i>
Nome Tab
</button>
</nav>
<!-- Tab Content -->
<div id="nome-tab" class="netgescon-tab-content active">
@include('path.to.tab-content', ['parametri' => $variabili])
</div>
2. Gestione Sicura Dati
<!-- Sempre usare nullsafe e default values -->
<p>{{ $oggetto?->proprieta ?? 'N/D' }}</p>
<!-- Per collezioni -->
<div>Totale: {{ $oggetto?->collezione?->count() ?? 0 }}</div>
<!-- Per date -->
<time>{{ $oggetto?->created_at?->format('d/m/Y') ?? 'N/D' }}</time>
3. Classi CSS Standardizzate
/* Mantenere consistenza classi */
.netgescon-tab-btn { /* Stili tab button */ }
.netgescon-tab-content { /* Stili contenuto tab */ }
.netgescon-btn { /* Stili bottoni */ }
.netgescon-card { /* Stili card */ }
🔄 SISTEMA TAB UNIFICATO
Implementazione JavaScript Standard
// File: resources/js/netgescon-tabs.js
class NetGesconTabs {
constructor() {
this.init();
}
init() {
document.addEventListener('DOMContentLoaded', () => {
this.bindEvents();
});
}
bindEvents() {
const tabButtons = document.querySelectorAll('.netgescon-tab-btn');
tabButtons.forEach(button => {
button.addEventListener('click', (e) => this.handleTabClick(e));
});
}
handleTabClick(event) {
const button = event.currentTarget;
const targetTab = button.dataset.tab;
if (!targetTab) return;
// Reset tutti i tab
this.resetAllTabs();
// Attiva tab selezionato
this.activateTab(button, targetTab);
// Carica contenuto dinamico se necessario
this.loadDynamicContent(targetTab);
}
resetAllTabs() {
document.querySelectorAll('.netgescon-tab-btn').forEach(btn => {
btn.classList.remove('active');
});
document.querySelectorAll('.netgescon-tab-content').forEach(content => {
content.classList.remove('active');
content.classList.add('hidden');
});
}
activateTab(button, targetTab) {
button.classList.add('active');
const targetContent = document.getElementById(targetTab);
if (targetContent) {
targetContent.classList.add('active');
targetContent.classList.remove('hidden');
}
}
loadDynamicContent(tabName) {
// Implementazione specifica per tab che richiedono caricamento dinamico
const dynamicTabs = ['unita-immobiliari', 'documenti-collegati'];
if (dynamicTabs.includes(tabName)) {
const container = document.getElementById(`${tabName}-content`);
if (container && !container.dataset.loaded) {
this.fetchTabContent(tabName, container);
}
}
}
async fetchTabContent(tabName, container) {
try {
const stabileId = window.stabileId || container.dataset.stabileId;
const response = await fetch(`/admin/stabili/${stabileId}/${tabName}`, {
headers: {
'X-Requested-With': 'XMLHttpRequest',
'Accept': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
}
});
const data = await response.json();
if (data.success) {
container.innerHTML = data.html;
container.dataset.loaded = 'true';
} else {
this.showError(container, 'Errore nel caricamento dei dati');
}
} catch (error) {
console.error('Errore caricamento tab:', error);
this.showError(container, 'Errore di connessione');
}
}
showError(container, message) {
container.innerHTML = `
<div class="text-center py-8">
<div class="text-red-600">
<i class="fas fa-exclamation-triangle text-2xl mb-2"></i>
<p>${message}</p>
</div>
</div>
`;
}
}
// Inizializza sistema tab
new NetGesconTabs();
🗄️ GESTIONE RELAZIONI DATABASE
Caricamento Sicuro Relazioni
// Nel Controller
public function show(Stabile $stabile)
{
// Carica relazioni in modo esplicito
$stabile->load([
'palazzine' => function($query) {
$query->orderBy('codice');
},
'unitaImmobiliari',
'datiBancari.contatto',
'tabelleMillesimali' => function($query) {
$query->orderBy('tipologia')->orderBy('anno', 'desc');
},
'documenti' => function($query) {
$query->orderBy('created_at', 'desc');
}
]);
return view('admin.stabili.show', compact('stabile'));
}
Validazione Dati Blade
<!-- Template sicuro per relazioni -->
@if($stabile && $stabile->relationLoaded('palazzine'))
@forelse($stabile->palazzine as $palazzina)
<!-- Contenuto -->
@empty
<!-- Messaggio vuoto -->
@endforelse
@else
<!-- Loading o messaggio alternativo -->
@endif
🐛 DEBUG E TESTING
1. Debug Veloce
// In Blade template - Solo per sviluppo
@if(config('app.debug'))
<div class="bg-yellow-100 p-2 text-xs">
Debug: {{ json_encode($stabile->palazzine?->count()) }}
</div>
@endif
2. Log Errori
// Nel Controller
try {
$data = $this->processData();
} catch (\Exception $e) {
\Log::error('Errore processamento dati: ' . $e->getMessage(), [
'file' => $e->getFile(),
'line' => $e->getLine(),
'stabile_id' => $stabile->id ?? null
]);
return back()->with('error', 'Errore nel caricamento dei dati');
}
3. Comandi Artisan Utili
# Pulizia cache
php artisan config:clear
php artisan view:clear
php artisan route:clear
# Debug rotte
php artisan route:list | grep stabili
# Test sintassi PHP
php -l resources/views/admin/stabili/show.blade.php
# Verifica database
php artisan migrate:status
✅ CHECKLIST PRE-DEPLOY
File da Controllare Sempre
- Sintassi PHP:
find . -name "*.php" -exec php -l {} \; - Blade Templates: Verificare tutti gli
@includeesistono - Relazioni Database: Controllare
?->per relazioni nullable - Rotte: Verificare tutte le
route()sono definite - JavaScript: Controllare selezione DOM e event listener
- CSS: Verificare classi standardizzate
- Immagini/Asset: Controllare percorsi file
Test Funzionalità
- Tab Navigation: Tutti i tab si aprono correttamente
- Form Submission: Creazione e modifica stabili
- AJAX Loading: Caricamento dinamico contenuti
- Error Handling: Gestione errori 404/500
- Mobile Responsive: Test su dispositivi mobili
Performance
- Query Optimization: Eager loading relazioni
- Cache: Configurazione cache attiva
- Assets: Minificazione CSS/JS
- Database: Indici su colonne utilizzate
📝 TEMPLATE COMMENTI CODICE
Blade Templates
{{--
NETGESCON TAB: [Nome Tab]
Descrizione: [Descrizione funzionalità]
Dipendenze: [Liste dipendenze]
Autore: GitHub Copilot
Data: 21/07/2025
--}}
{{-- Header Tab con controlli --}}
<div class="flex justify-between items-center">
{{-- Titolo e descrizione --}}
<div>
<h4 class="text-xl font-semibold text-gray-900">
<i class="fas fa-icon mr-2 text-color"></i>
Titolo Tab
</h4>
<p class="text-sm text-gray-600 mt-1">
Descrizione funzionalità tab
</p>
</div>
{{-- Pulsanti azione --}}
<div class="space-x-2">
<!-- Pulsanti azione -->
</div>
</div>
JavaScript
/**
* NETGESCON: [Nome Funzione]
* Descrizione: [Descrizione funzionalità]
*
* @param {type} parametro - Descrizione parametro
* @returns {type} Descrizione return
*
* @author GitHub Copilot
* @date 21/07/2025
* @version 1.0.0
*/
function nomeFunction(parametro) {
// Implementazione
}
🎯 PROSSIMI PASSI
- Implementare Sistema Seeder per dati demo persistenti
- Creare Test Automatici per prevenire regressioni
- Ottimizzare Performance con eager loading
- Documentare API per integrazioni future
- Setup CI/CD per deploy automatici
📞 SUPPORTO TECNICO
Per problemi urgenti, consultare sempre questo manuale prima di procedere con modifiche al codice.
🔄 AGGIORNAMENTI
Questo manuale verrà aggiornato ad ogni sessione di sviluppo con nuovi problemi risolti e best practices.