So when I initially put my hands on Laravel, I was transistioning off Yii1. In Yii, we'd use plain PHP templates; which I don't mind, since I actually like them that way.
However, when I learned about Blade and how Laravel documented Blade back and forth and barely even mentioned the use of bare PHP templates, I was...irked.
I threw together a project that would provide me with just a PHP view engine. But just a few minutes ago, I actually saw it: PhpEngine.php. Diggin deeper, I facepalmed; I can not just go and deprecated my project, but I can also go and dig deeper.
It is sooo confusing, so I am looking ot have a teeny tiny bit of questions answered:
When I use View::addNamespace(), I can just do view("foo::my.template") too, right?
How do I actually use a layout/template? As in, I have the document written, into which I want to rende rmy views. How do I do that with bare PHP views? IN blade, we get #extend or something, but I can not seem to find that for raw PHP templates.
Where can I see some proper view docs and examples instead of the laravel.com ones, which push Blade that much?
When I use view::addNamespace(), I can just do view("foo::my.template") too, right?
Yes. It does. Generally this format is applied third party packages. For example, if you have in mind using a package, you call the view namespace as:
$this->loadViewsFrom(__DIR__.'/path/to/views', 'foo');
Now you are able to call view as view('foo::whatever')
How do I actually use a layout/template? As in, I have the document written, into which I want to rende rmy views. How do I do that with bare PHP views? IN blade, we get #extend or something, but I can not seem to find that for raw PHP templates.
I do not understand what I can not seem to find that for raw PHP templates means. But let me show you an example using blade system:
Create a layout file:
// master.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<title>#yield('title')</title>
<head>
<body>
#yield('body')
</body>
</html>
As you can notice above, there are two "sections" that their content can be changed according to each view that extends this layout: title and body.
Extending the layout for each view
//contact.blade.php
#extends('master')
#section('title')
Contact us
#stop
#section('body')
<h1>Thank you for contact us</h1>
#stop
Notice how title and body are set using #section tag. Inside of each one you define the content to be displayed. Finally, in your controller just call view('foo::contact') or view('contact') according to your needs.
Where can I see some proper view docs and examples instead of the laravel.com ones, which push Blade that much?
Well, blade system is not too much deep. I consider that laravel's docs is enough complementing your knowledge with this side.
Related
Excuse me, i would like to ask about how to call another page blade in different subfolder inside views.
Example :
views
--home(subfolder)
--beranda(subfolder)
--refresh.blade.php
--layouts(subfolder)
--master.blade.php
in master.blade.php implements template page, when i click one link in this folder may have to go in refresh.blade.php.
Likely another web layout, they have a lot of link in header like 'Home', 'Paper', etc.
I'm still learned more about laravel as beginner practice.
May you can help me, i'll appreciate that.
Regard, Aga.
I think you can refer to some directives such as #include and #extends in the laravel blade.
For example, in the admin.common.header view (located at admin/common/header.blade.php), we have some basic page code (common to various pages such as navigation bar or layout). We use #yield such as #yield ("extra_js") or #yield ("extra_css") where we want to add code later.
header.blade.php
<html>
<head>
something maybe ...
#yield("extra_css")
</head>
<body>
something maybe ...
#yield("extra_js")
</body>
</html>
And in another view such as admin.feedback.feedback, you can use #extends('admin.common.header') at the top of the code to inheritance the template and you will get the layout of this template.
For different content in the feedback template, you can use #section to give you code to fill in the inheritance template such as #section('extra_js').
feedback.blade.php
#extends('admin.common.header')
#section('extra_js')
<script> something... </script>
#endsection
If you want to include one blade, just use #include.
<div>
#include('shared.errors')
<form>
<!-- Form Contents -->
</form>
</div>
In laravel blade there are many instructions to complete the rendering of the template, if you want to know clearly, please refer to the corresponding version of the official document.
It's not really a big problem, but it is mighty annoying.
When starting creating templates in laravel using blade, everything looks fine. The "master" template/layout gets it's "styling" correct. And by "styling" i mean like correct amount of whitespaces, newlines etc when viewing the source code.
The problem occurs when you know try to extend this master template.
for every #section('<something>') you do know, all newlines is removed from the code, making the source code look fuggly.
Have been searching this phenomenon for a while without finding anything interesting which explains why or maybe a solution to make the source code readable again.
Here is an example if the explanation wasn't good enough:
// master.blade.php
<html>
<head>
<title>Something here</title>
</head>
<body>
#yield('content')
</body>
</html
Alright, this will look exactly like this in the source code. Let's make a another template which extends this.
// home.blade.php
#extends('master')
#section('content')
<h1>Welcome</h1>
<p>This is my homepage</p>
#endsection
This will first of inherit the parent, and replace #yield('content') with:
<h1>Welcome</h1> <p>This is my homepage</p>
Is there any explanation at all why this happens?
For longer sub-templates reading the source code is a living hell. Best way to see the "source code" is to see the generated one in inspect element, which also is just the live code, and not the first generated.
- Sligthly annoyed developer
I believe this is up to Laravels way of handling views. Every blade-view you create in resources/views will be "translated" to PHP. This line in your code for example:
#yield('content')
will be translated to
<?php echo $__env->yieldContent('content'); ?>
you can easely check for yourself by checking all files at storage/framework/views/. This are the files Laravel will include to build the "real" HTML website. Note, that all tab-stops made in .blade.php views are replaced with 4 spaces. And there are this ugly intendations.
If I have 10 images, 2 javascript files, and 4 css files that need to be included inside a Ci view... How is the best way to call all the files? I've tried calling all the external files using $this->load->view('image1.png') and $this->load->view('style.css'). But it doesn't seem to work properly. Any ideas on how to better approach this problem?
You're not using the view method correctly there.
You typically assign one view and pass things like js and css to the template. This can vary depending on how you use the framework.
$this->load->view('path-to-view'); will look for a view in the view folder and not an arbitrary file.
You might look into this:
http://codeigniter.com/user_guide/helpers/html_helper.html#img
for loading images, though I personally think it's pointless to call a framework's method for a basic html element like an image.
There are cases when you would use multiple views, like views to be returned as strings - loops and such may need these - but that doesn't look like the case in your question.
Just in case though here's the view docs:
http://codeigniter.com/user_guide/general/views.html
To elaborate further, the general idea is to use the CI controller to handle the data for your page, pass the necessary template data to the template (like your js and css specific to this page) then assign the necessary data to the view and pass that view to the template. You may be wondering what I mean by template too, since out of box CI loads views progressively if you just call them sequentially.
in your controller you may pass the view an array of header info:
$data['css'] = array('some-path.css','another-path.css');
$this->load->view('your-view', $data);
so in your view that handles the header you might call something like this:
<head>
<?php foreach($css AS $c): ?>
<link rel="stylesheet" type="text/css" href="<?php echo $c; ?>">
<?php endforeach; ?>
</head>
Here's a fair link to CI templates:
How to Deal With Codeigniter Templates?
It's a versatile framework with many options for using it however you are most comfortable.
I created a custom PHP templating system and the way I built it seems, well, inefficient. The three main goals for my template was to:
Pull all site-wide HTML elements from a template.tpl include.
Be able to dynamically assign content in the template.tpl (like <title> or <script>)
Be as efficient and scalable as possible.
In the end, my template system looked something like this:
randomPage.php
<?php
// declare any page specific resources
$pageTitle = "Random Sub-Title";
$pageResources = "/css/someRandomCSS.css"
$pageContent = "/randomPage.tpl"
// include the generic page template
include dirname($_SERVER['DOCUMENT_ROOT']).'/includes/template.tpl'
?>
randomPage.tpl
<h1><?=$pageTitle?></h1>
<p>Some random page's content</p>
template.tpl
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Site -- <?=$pageTitle?></title>
<link href="/css/styles.css" rel="stylesheet" type="text/css">
<link href="<?=pageResources?>" rel="stylesheet" type="text/css">
</head>
<body>
<? include $pageContent ?>
</body>
</html>
The main problem with this system is that for every web page, I need to manage two files: one for logic/data and the other for the page template. This seems largely inefficient to me, and doesn't seem like a very scalable approach.
Recently, I come across the smarty framework, which would allow me to consolidate my system from randomPage.php and randomPage.tpl into something like:
randomSmartyPage.php
{extends file="template.tpl"}
{block name=pageTitle}My Page Title{/block}
{block name=pageResources}
<link href="/css/someRandomCSS.css" rel="stylesheet" text="text/css">
{/block}
{block name=pageContent}My HTML Page Body goes here{/block}
Seeing this approach raised three major questions for me:
Are there any fundamental flaws with how I am approaching my templating system?
Can my original php code be refactored so I don't have to create two files for every web page?
Would using the smarty (or perhaps an alternative framework) be a good idea in this case?
Your code isn't really using any templating engine besides PHP itself, which is fine. A flaw I can see is your template will have access to all variables, and the ones you create for it are all global.
Two files is a good system, one to change what is preprocessed and passed to the view, and one for the view itself, containing HTML or whatever. This allows you to easily swap views, for example, a view for standard browsing and a mobile view for mobile browsers.
It can be a good idea, but I'm a firm believer that using PHP is good enough.
Here is an example, untested. It will encapsulate all the variables so you don't pollute the global namespace.
index.php
function view($file, $vars) {
ob_start();
extract($vars);
include dirname(__FILE__) . '/views/' . $file . '.php';
$buffer = ob_get_contents();
ob_end_clean();
return $buffer;
}
echo view('home', array('content' => Home::getContent()));
views/home.php
<h1>Home</h1>
<?php echo $content; ?>
The approach you are describing is part of MVC design pattern. Separating the different aspects of your application.
What you seem to have already understood is that PHP is a templating system in itself as have many others before you.
Take a look at this benchmark for a rough comparison of popular template systems.
Update 2022.08.29
Updated broken links to archived versions.
Note: The answer remains valid if you're trying to learn the language. But for anything serious, consider using a framework.
I've got some scripts I'd like to add to the end of the <body> of the page, and some that I need to have in the <head>. I'm wondering if there's a more elegant way to add certain scripts to the <head> and certain in the <body> using a segment or something like that. Say I have two scripts that are going to go in the body:
$this->view->headScript()->prependFile($assetUrl . "/js/jquery.min.js");
$this->view->headScript()->appendFile($assetUrl . "/js/application.js");
And I want this one in the <head> instead:
$this->view->headScript()->prependFile($assetUrl . "/js/modernizr.min.js");
Calling $this->headScript(); outputs all three in both cases. Is there a way to group scripts? I could just paste the HTML snippet manually, but I'd like to have it in code because I switch to minified versions of the javascript if the site is running in the production environment.
I'd make my own helper called htmlScript. You should be able to extend the existing headScript helper, overriding the registry key property only.
Then just echo out your helper in your layout at the end of the document
<?php echo $this->htmlScript() ?>
Edit Been out of the loop for too long ;)
There's already a helper for you - Zend_View_Helper_InlineScript
If you want to override the script files:
$this->view->headScript()->setFile()
EDIT I'm not sure why I got downvoted. I gave an alternative answer to your question, albeit succinctly. If you have prepended/appended two script files, but for a specific controller or module you wish to override the loading of those scripts with a third, then setFile should do exactly what you asked.