Laravel 5 - Compile String and Interpolate Using Blade API on Server - laravel

Using the Blade service container I want to take a string with markers in it and compile it down so it can be added to the blade template, and further interpolated.
So I have an email string (abridge for brevity) on the server retrieved from the database of:
<p>Welcome {{ $first_name }},</p>
And I want it to interpolated to
<p>Welcome Joe,</p>
So I can send it to a Blade template as $content and have it render all the content and markup since Blade doesn't interpolate twice and right now our templates are client made and stored in the database.
Blade::compileString(value) produces <p>Welcome <?php echo e($first_name); ?>,</p>, but I can't figure out how to get $first_name to resolve to Joe in the string using the Blade API, and it doesn't do it within the Blade template later. It just displays it in the email as a string with PHP delimiters like:
<p>Welcome <?php echo e($first_name); ?>,</p>
Any suggestions?

This should do it:
// CustomBladeCompiler.php
use Symfony\Component\Debug\Exception\FatalThrowableError;
class CustomBladeCompiler
{
public static function render($string, $data)
{
$php = Blade::compileString($string);
$obLevel = ob_get_level();
ob_start();
extract($data, EXTR_SKIP);
try {
eval('?' . '>' . $php);
} catch (Exception $e) {
while (ob_get_level() > $obLevel) ob_end_clean();
throw $e;
} catch (Throwable $e) {
while (ob_get_level() > $obLevel) ob_end_clean();
throw new FatalThrowableError($e);
}
return ob_get_clean();
}
}
Usage:
$first_name = 'Joe';
$dbString = '<p>Welcome {{ $first_name }},</p>';
return CustomBladeCompiler::render($dbString, ['first_name' => $first_name]);
Thanks to #tobia on the Laracasts forums.

Related

File isn't deleted when code is in a specific order

I ran into the problem that when I try to delete a record from database using ->delete() and my code stopped after successfully deleted the record.
This code doesn't execute the Storage::delete($image)
public function productImageDelete(Request $request){
if($request->ajax()):
$image_id = Input::get('image-id');
$image = Input::get('image');
try {
$image = Image::findOrFail($image_id);
$image->delete();
Storage::delete($image); //This doesn't execute at all
return "success";
} catch ( \Illuminate\Database\QueryException $e) {
return $e;
}
endif;
}
However when I placed Storage::delete($image) before $image->delete(); the code works.
public function productImageDelete(Request $request){
if($request->ajax()):
$image_id = Input::get('image-id');
$image = Input::get('image');
try {
Storage::delete($image); //This executes first
$image = Image::findOrFail($image_id);
$image->delete();
return "success";
} catch ( \Illuminate\Database\QueryException $e) {
return $e;
}
endif;
}
You need to take a look at the details. You're creating two variables named $image and that's your issue.
On the first case, you're calling Storage::delete($image); where $image is an object and on the second case, you're calling the same method but in that case $image is a Input::get('image').
If you simply rename the variable of Input::get('image') to, say $imageParam = Input::get('image') and execute Storage::delete($imageParam);, it should work on both cases.
The bottomline is: never use the same variable name, as it will led to such unnecessary confusions.

ReCaptcha For Newbies

I've got ReCaptcha working but despite reading the documentation and the answers posted here, I'm still at a loss for setting up the server side. My HTML form calls <form id="contactForm" class="well" method="POST" action="php/contactform.php">.
What and where do I place the server-side recaptcha in this file? (I meant it when I titled this newbie. I really need explicit instructions):
<?php
if($_POST){
// response hash
$response = array('message'=>'');
}
try {
// Get values from form
$name=$_POST['cname'];
$email=$_POST['cemail'];
$subject=$_POST['csubject'];
$message=$_POST['cmessage'];
$formcontent="From: $name \n Email: $email \n Subject: $subject \n: $message";
$recipient = "rabbidubrow#fivegates.org";
$subject = "KHF Contact Form";
$mailheader = "From: $email \r\n";
$send_contact=mail($recipient, $subject, $formcontent, $mailheader) or die("Error!");
// let's assume everything is ok, setup successful response
$response['type'] = 'success';
$response['message'] = 'Thank you! We will be in touch shortly.';
} catch(Exception $e){
$response['type'] = 'error';
$response['message'] = $e->getMessage();
}
// now we are ready to turn this hash into JSON
print json_encode($response);
exit;
?>
You will need
1. Include your recaptcha.php
2. Declare your private and public keys
3. Check for POST of your captcha. If it success, give a response, if it fails, catch the exception.
Below is one of my scripts that was done up for your reference.
require_once('assets/config/recaptchalib.php');
$publickey = "xxxx";
$privatekey = "xxxxx";
if ($_POST["recaptcha_response_field"]) {
$resp = recaptcha_check_answer ($privatekey, $_SERVER["REMOTE_ADDR"], $_POST["recaptcha_challenge_field"], $_POST["recaptcha_response_field"]);
if ($resp->is_valid) {
$continue = true;
}
}

redirect issue in codeigniter when using if statement

i have been trying to redirect the same previous page after delete or inserting the data using if condition in the controller to flash the message but there is something i am missing.
<form action="<?php echo base_url(); ?>curdler/add/tbl_category/addCat/category" method="post">
Category Title<input type="text" name="category_title"/> </br>
<input type ="submit" value="submit">
</form>
<?php echo $this->session->flashdata('msg'); ?>
Controller
public function add() {
$data = $_POST;
$tableName = $this->uri->segment(3);
$content = $this->uri->segment(4);
$folderName = $this->uri->segment(5);
$this->load->model('curdmodel');
if($this->curdmodel->add($data, $tableName)){
$this->session->set_flashdata('msg', 'Category added');
redirect('welcome/index/'.$content.'/'.$folderName);
} else{
$this->session->set_flashdata('msg', 'Category Not Added');
}
}
when using the if statement it goes to the different url but without if statement its working fine.
model
public function add($data, $tableName) {
$this->db->insert($tableName, $data);
}
Your redirect only occurs if the if statement evaluates to be true, if the condition is false codeigniter is just setting the flashdata and then ending the script.
Consider changing the order of your code to something like
if($this->curdmodel->add($data, $tableName)){
$this->session->set_flashdata('msg', 'Category added');
} else{
$this->session->set_flashdata('msg', 'Category Not Added');
}
redirect('welcome/index/'.$content.'/'.$folderName);
Additionally, your model does not contain any return value and therefore will never pass data back for the if statement to be evaluated. You should update your model as follows:
public function add($data, $tableName) {
$this->db->insert($tableName, $data);
if($this->db->affected_rows() > 0) {
return true;
}
}

Blade :: compileString() and embedded variables

I am able to parse HTMl that uses blade template variables through the following code:
$generated = Blade::compileString($string);
ob_start();
try
{
eval($generated);
}
catch (\Exception $e)
{
ob_get_clean(); throw $e;
}
$content = ob_get_clean();
return $content;
And it works fine as long as i don't use blade variables within. Which on being parsed give me undefined variable error. How can i make sure that blade variables are available in my custom parsing method?
This works for me with the latest version of Laravel 5.7. Notice how I include the __env var so that functions like #include, #foreach, etc can work.
public static function renderBlade($string, $data = null)
{
if (!$data) {
$data = [];
}
$data['__env'] = app(\Illuminate\View\Factory::class);
$php = Blade::compileString($string);
$obLevel = ob_get_level();
ob_start();
extract($data, EXTR_SKIP);
try {
eval('?' . '>' . $php);
} catch (Exception $e) {
while (ob_get_level() > $obLevel) {
ob_end_clean();
}
throw $e;
} catch (Throwable $e) {
while (ob_get_level() > $obLevel) {
ob_end_clean();
}
throw new FatalThrowableError($e);
}
return ob_get_clean();
}
Turns out I was not passing the arguments array to the method that parses the Blade structure. My assumption was that the Mail::send method takes care of making variables available which it takes in as a second parameter. I also had to extract($args, EXTR_SKIP).
$generated = Blade::compileString($string);
ob_start(); extract($args, EXTR_SKIP)
try
{
eval($generated);
}
catch (\Exception $e)
{
ob_get_clean(); throw $e;
}
$content = ob_get_clean();
return $content;

Magento Product Images Full URL Path Instead of Cached

The code below works for products that have images, but for products that don't have images, the placeholder small image doesn't show.
echo Mage::getModel('catalog/product_media_config')->getMediaUrl( $_product->getSmallImage());
<?php
// get image full url
echo $imageUrl = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA) . 'catalog/product' . $_product->getImage();
// get image using custom size with url
echo $imageCacheUrl = Mage::helper('catalog/image')->init($_product, 'image')->resize(135,135);
?>
The code that affects what you want to do is
//file: app/code/core/Mag/Catalog/Helper/Image.php
//class: Mage_Catalog_Helper_Image
/**
* Return Image URL
*
* #return string
*/
public function __toString()
{
try {
//...
} catch (Exception $e) {
$url = Mage::getDesign()->getSkinUrl($this->getPlaceholder());
}
return $url;
}
The interesting line is
$url = Mage::getDesign()->getSkinUrl($this->getPlaceholder());
So in your code you need to test the return value of $_product->getSmallImage() and if it is false or null use Mage::getDesign()->getSkinUrl($this->getPlaceholder()); instead.
You might want to inspect $_product->getSmallImage() to see what it returns when no value is set.
Oh, and I just checked: getPlaceholder() is a function not a magic getter. This is the function:
public function getPlaceholder()
{
if (!$this->_placeholder) {
$attr = $this->_getModel()->getDestinationSubdir();
$this->_placeholder = 'images/catalog/product/placeholder/'.$attr.'.jpg';
}
return $this->_placeholder;
}
So you will have to unravel some $this (hint $this->_getModel() is Mage::getModel('catalog/product_image') )
or to cut a long story short just fall back to the default:
echo ($this->helper('catalog/image')->init($_product, 'small_image'));
in your phtml file if $_product->getSmallImage() doesn't exist.
Update following your comment:
Specifcically in the .phtml file that you are using to generate the HTML that displays the small image you could write:
$testSmallImageExists = $_product->getSmallImage();
if($testSmallImageExists)
{
echo Mage::getModel('catalog/product_media_config')->getMediaUrl( $_product->getSmallImage());
}
else
{
echo ($this->helper('catalog/image')->init($_product, 'small_image'));
}
Or just simply use
echo ($this->helper('catalog/image')->init($_product, 'small_image'));
I'm sure that is the standard Magento way.

Resources