|
| 1 | +# Content |
| 2 | + |
| 3 | +Learn how to work with content in your frontend templates. |
| 4 | + |
| 5 | +## Content Helper |
| 6 | + |
| 7 | +The `inspirecms_content()` helper provides access to content items throughout your frontend templates: |
| 8 | + |
| 9 | +```php |
| 10 | +// Get content by ID |
| 11 | +$content = inspirecms_content()->findByIds(ids: '550e8400-e29b-41d4-a716-446655440000', limit: 1)->first(); |
| 12 | + |
| 13 | +// Get content by slug |
| 14 | +$content = inspirecms_content()->findByRealPath(path: 'about-us', limit: 1)->first(); |
| 15 | + |
| 16 | +// Get multiple content items |
| 17 | +$contents = inspirecms_content()->findByIds(['550e8400-e29b-41d4-a716-446655440000', '7f1b96c0-d4f0-11ed-afa1-0242ac120002']); |
| 18 | + |
| 19 | +// Get published content under 'home' |
| 20 | +$contents = inspirecms_content()->getUnderRealPath(path: 'home', isPublished: true); |
| 21 | + |
| 22 | +// Get paginated published content under 'home' |
| 23 | +$contents = inspirecms_content()->getPaginatedUnderRealPath(path: 'home', isPublished: true, page: 1, perPage: 10); |
| 24 | + |
| 25 | +// Get content by document type |
| 26 | +$blogPosts = inspirecms_content()->getByDocumentType(documentType: 'blog_post', isPublished: true); |
| 27 | + |
| 28 | +// Get paginated content by document type |
| 29 | +$blogPosts = inspirecms_content()->getPaginatedByDocumentType(documentType: 'blog_post', isPublished: true, page: 1, perPage: 10); |
| 30 | +``` |
| 31 | + |
| 32 | +## Accessing Content Properties |
| 33 | + |
| 34 | +### Basic Properties |
| 35 | + |
| 36 | +Access core content attributes: |
| 37 | + |
| 38 | +```php |
| 39 | +$title = $content->getTitle(); // Get content title |
| 40 | +$slug = $content->slug; // Get content slug |
| 41 | +$url = $content->getUrl(); // Get content URL |
| 42 | +$locale = $content->getLocale(); // Get content locale |
| 43 | +$publishedAt = $content->publishAt; // Publication date |
| 44 | +``` |
| 45 | + |
| 46 | +### Custom Fields |
| 47 | + |
| 48 | +Use property directives in Blade templates to access custom fields: |
| 49 | + |
| 50 | +```php |
| 51 | +<!-- Single property --> |
| 52 | +<h1>@property('hero', 'title')</h1> |
| 53 | + |
| 54 | +<!-- With custom variable name --> |
| 55 | +@property('hero', 'images', 'custom_images') |
| 56 | +@foreach($custom_images ?? [] as $image) |
| 57 | + <img src="{{ $image->getUrl() }}"> |
| 58 | +@endforeach |
| 59 | + |
| 60 | +<!-- Value is from $blogDTO, variable available as $blog_category --> |
| 61 | +@property('blog', 'category', null, $blogDTO) |
| 62 | + |
| 63 | +<!-- Array properties --> |
| 64 | +@propertyArray('gallery', 'images') |
| 65 | +@foreach($gallery_images ?? [] as $image) |
| 66 | + <img src="{{ $image->getUrl() }}" alt="{{ $image->alt_text }}"> |
| 67 | +@endforeach |
| 68 | + |
| 69 | +<!-- Conditional display --> |
| 70 | +@propertyNotEmpty('hero', 'button_text') |
| 71 | + <a href="@property('hero', 'button_link')" class="btn"> |
| 72 | + {{ $hero_button_text }} |
| 73 | + </a> |
| 74 | +@endif |
| 75 | +``` |
| 76 | + |
| 77 | +You can also access properties programmatically: |
| 78 | + |
| 79 | +```php |
| 80 | +// Check if property exists |
| 81 | +if ($content->hasProperty('hero', 'title')) { |
| 82 | + // Get property value |
| 83 | + $title = $content->getPropertyValue('hero', 'title'); |
| 84 | + |
| 85 | + // Get property value with fallback |
| 86 | + $subtitle = $content->getPropertyValue('hero', 'subtitle') ?? 'Default subtitle'; |
| 87 | + |
| 88 | + // Get multilingual property with specific locale |
| 89 | + $frenchTitle = $content->getPropertyValue('hero', 'title', 'fr'); |
| 90 | +} |
| 91 | + |
| 92 | +// Check if property group exists |
| 93 | +if ($content->hasPropertyGroup('hero')) { |
| 94 | + // Get entire property group |
| 95 | + $heroGroup = $content->getPropertyGroup('hero'); |
| 96 | +} |
| 97 | +``` |
| 98 | + |
| 99 | +## Content Relationships |
| 100 | + |
| 101 | +Access related content and structure: |
| 102 | + |
| 103 | +```php |
| 104 | +// Get parent content |
| 105 | +$parent = $content->getParent(); |
| 106 | + |
| 107 | +// Get all child content |
| 108 | +$children = $content->getChildren(); |
| 109 | + |
| 110 | +// Get ancestors in hierarchical order |
| 111 | +$ancestors = $content->getAncestors(); |
| 112 | +``` |
| 113 | + |
| 114 | +## Content Filtering and Sorting |
| 115 | + |
| 116 | +Filter and sort content collections: |
| 117 | + |
| 118 | +```php |
| 119 | +// Get recent blog posts |
| 120 | +$recentPosts = inspirecms_content()->getUnderRealPath( |
| 121 | + path: 'blogs', |
| 122 | + isPublished: true, |
| 123 | + sorting: ['__latest_version_publish_dt' => 'desc'], |
| 124 | + limit: 5, |
| 125 | +); |
| 126 | + |
| 127 | +// Get paginated recent blog posts |
| 128 | +$recentPosts = inspirecms_content()->getPaginatedUnderRealPath( |
| 129 | + path: 'blogs', |
| 130 | + page: 1, |
| 131 | + perPage: 10, |
| 132 | + isPublished: true, |
| 133 | + sorting: ['__latest_version_publish_dt' => 'desc'], |
| 134 | +); |
| 135 | + |
| 136 | +// Filter by custom fields |
| 137 | +$featuredPosts = inspirecms_content()->getByDocumentType( |
| 138 | + documentType: 'blog_post', |
| 139 | + limit: 50, |
| 140 | + ) |
| 141 | + ->toDto($locale ?? app()->getLocale()) |
| 142 | + ->filter(function($post) { |
| 143 | + return $post->getPropertyValue('blog', 'is_featured') === true; |
| 144 | + }); |
| 145 | +``` |
| 146 | + |
| 147 | +## Working with Multiple Languages |
| 148 | + |
| 149 | +Access content in different languages: |
| 150 | + |
| 151 | +```php |
| 152 | +// Get content in specific language |
| 153 | +$frenchContent = $contentModel->toDto('fr'); |
| 154 | + |
| 155 | +// Check if content is available in a language |
| 156 | +$hasSpanish = $content->hasTranslation('es'); |
| 157 | + |
| 158 | +// Loop through all available translations |
| 159 | +foreach (inspirecms()->getAllAvailableLanguages() as $locale => $langDto) { |
| 160 | + $translatedTitle = $content->getTitle($locale); |
| 161 | + // Do something with the translation |
| 162 | +} |
| 163 | +``` |
| 164 | + |
| 165 | +## Pagination |
| 166 | + |
| 167 | +Paginate content collections: |
| 168 | + |
| 169 | +```php |
| 170 | +// In your controller |
| 171 | +$paginatedContent = inspirecms_content()->getPaginatedByDocumentType(documentType: 'blog_post', perPage: 10); |
| 172 | + |
| 173 | +// In your Blade template |
| 174 | +@foreach ($paginatedContent as $post) |
| 175 | + <h2>{{ $post->getTitle() }}</h2> |
| 176 | + <p>{{ $post->getPropertyValue('blog', 'excerpt') }}</p> |
| 177 | +@endforeach |
| 178 | + |
| 179 | +{{ $paginatedContent->links() }} |
| 180 | +``` |
| 181 | + |
| 182 | +## Customizing Services |
| 183 | + |
| 184 | +You can customize any service by binding your own implementation in your ServiceProvider's `boot` method: |
| 185 | + |
| 186 | +```php |
| 187 | +use SolutionForest\InspireCms\Services\ContentServiceInterface; |
| 188 | + |
| 189 | +public function boot() |
| 190 | +{ |
| 191 | + // Customizing Content Service |
| 192 | + $this->app->singleton(ContentServiceInterface::class, fn () => new YourContentService()); |
| 193 | +} |
| 194 | +``` |
| 195 | + |
| 196 | +```php |
| 197 | +use SolutionForest\InspireCms\Services\ContentServiceInterface; |
| 198 | + |
| 199 | +class YourContentService implements ContentServiceInterface |
| 200 | +{ |
| 201 | + |
| 202 | +} |
| 203 | +``` |
| 204 | + |
| 205 | +## Best Practices |
| 206 | + |
| 207 | +- Use `inspirecms_content()` helper for retrieving content instead of direct database queries |
| 208 | +- Always check if properties exist before using them |
| 209 | +- Cache frequent content queries for better performance |
| 210 | +- For large content sets, use pagination to improve page load times |
| 211 | +- Use property directives in Blade templates for cleaner syntax |
0 commit comments