Custom blade directives not working - syntax error, unexpected ')' - laravel

I'm trying to create a blade directive that checks if the User is logged in AND has an activated account. In our database, we have a user_status column with 0: pending, 9 active.
// AppServiceProvider.php
public function boot()
{
Blade::directive('active', function () {
$condition = false;
// check if the user is authenticated
if (Auth::check()) {
// check if the user has a subscription
if(auth()->user()->getStatus() == 9) {
$condition = true;
} else {
$condition = false;
}
}
return "<?php if ($condition) { ?>";
});
Blade::directive('inactive', function () {
return "<?php } else { ?>";
});
Blade::directive('endactive', function () {
return "<?php } ?>";
});
}
// welcome.blade.php
#active
<p>User is active</p>
#inactive
<p>User is inactive</p>
#endactive
I have included this getStatus() function on my User.php model.
public function getStatus() {
return $this->user_status;
}
I can also use the Trait MustActivateAccount, which includes this feature:
/**
* Determine if the user has activated account.
*
* #return bool
*/
public function hasActivatedAccount()
{
return $this->user_status == 9;
}
This blade directive when added to the page says this error:
Facade\Ignition\Exceptions\ViewException
syntax error, unexpected ')'
Am I not escaping correctly in the AppServiceProvider.php file and if so where and how?

You can try this in your blade template
#if(Auth()->user()->user_status == 9)
<p>User is active</p>
#else
<p>User is inactive</p>
#endif

I had the same issue and the solution turned out to be the boolean $condition variable that had to be set as a string. $condition = "true"; and not $condition = true.
This makes sense since the boolean would not echo out. Thus it would be <?php if() { ?> and not <?php if(true) { ?>.
See below (current version 6.18.41):
// check for Providers
Blade::directive('provider', function () {
// check if the user has the correct type
$condition = Auth::user()->type === "provider" ? "true" : "false"; // ... and not boolean
return "<?php if (" . $condition . ") { ?>";
});
Blade::directive('endprovider', function () {
return "<?php } ?>";
});
... and run: php artisan view:clear

Related

How to fix error: count(): Parameter must be an array or an object that implements Countable

A PHP Error was encountered
Severity: Warning
Message: count(): Parameter must be an array or an object that implements Countable
Filename: models/login_model.php
Line Number: 17
Backtrace:
File: C:\xampp\htdocs\labexercise007\application\models\login_model.php
Line: 17
Function: _error_handler
File: C:\xampp\htdocs\labexercise007\application\controllers\login.php
Line: 31
Function: login
File: C:\xampp\htdocs\labexercise007\application\controllers\login.php
Line: 14
Function: run
<?php
class login_model extends CI_Model
{
public function __construct()
{
parent::__construct();
$this->load->database();
}
public function login($username, $password)
{
$condition_array = array(
'user_name' => $username,
'user_pass' => md5($password)
);
$rs = $this->db->get_where('users', $condition_array);
$row_count = count($rs->row_array());
if ($row_count > 0) {
return $rs->row_array();
} else {
return FALSE;
}
}
}
<?php
class Login extends CI_Controller
{
public function index()
{
$data['title'] = 'Login';
$this->load->view('login', $data);
}
public function verify()
{
$this->form_validation->set_rules('txtuser', 'Username', 'required');
$this->form_validation->set_rules('txtpass', 'Password', 'required|callback_check_user');
if ($this->form_validation->run() === TRUE) {
if ($this->session->user_lvl == 1) {
redirect('admin/home');
} else {
redirect('home');
}
} else {
$this->index();
}
}
public function check_user()
{
$username = $this->input->post('txtuser');
$password = $this->input->post('txtpass');
$this->load->model('login_model');
$login = $this->login_model->login($username, $password);
if ($login) {
$sess_data = array(
'account_name' => $login['user_accountname'],
'user_lvl' => $login['user_lvl'],
'islogged' => TRUE
);
$this->session->set_userdata($sess_data);
return true;
} else {
$this->form_validation->set_message('check_user', 'Invalid Username/password');
return false;
}
}
}
PHP v7.2.0 count() will now yield a warning on invalid countable types passed to the array_or_countable parameter.
see more
If your result set is empty, the row_array() value is NULL and you cannot use count on it. Check what row_array() returns before counting.
Later edit
Try removing this block:
if ($row_count > 0) {
return $rs->row_array();
} else {
return FALSE;
}
And replacing it with a ternary operator call:
return $rs->row_array() ?: false;
This should solve your warning and return the proper result.
Did you try to get the result array? in the documentation in query builder it gives like this.
$row_count = count($rs->getResultArray()) ;
in this case it will always return an array even if you do not have a result in query.
Instead of counting the row array that might be null in your case so you don't have a countable object or array you should count your query results.
$row_count = count($rs->row_array());
Instead use the count records function built in the query builder.
public function login($username, $password)
{
$condition_array = array(
'user_name' => $username,
'user_pass' => md5($password)
);
$rs = $this->db->from('users')->where($condition_array)->get();
$row_count = $this->db->num_rows();
if ($row_count > 0) {
return $rs->row_array();
}
return FALSE;
}
Changed the function to remove the else statement because it was not needed in this case.
Also, I might add that you shouldn't be using MD5 to encrypt your passwords. MD5 is not really secure at this point.
More information on counting database results on codeigniter 3: https://codeigniter.com/userguide3/database/query_builder.html?highlight=count#limiting-or-counting-results
In Model:
function getPaymentTotalCount($search)
{
$sql = 'SELECT id FROM tbl_payment WHERE '.$search;
$query = $this->db->query($sql);
return $query->num_rows(); // <- replace row() to num_rows()
}

Error in Custom Blade Directives with array as parameter

In my Laravel 5.7 app I want to use Custom Blade Directives and to pass an array in this directive
as there could be different access, like :
#loggedUserHasAccess([USER_ACCESS_ADMIN])
<div class="col">
<a class="social-inner" href="{{ route('admin.dashboard') }}" >
<span class="icon"></span><span>Backend</span>
</a>
</div>
#endLoggedUserHasAccess
And in app/Providers/AppServiceProvider.php :
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
...
\Blade::directive('loggedUserHasAccess', function (array $accessArray) {
$condition = false;
if (Auth::check()) {
$loggedUser = Auth::user();
$usersGroups = User::getUsersGroupsByUserId($loggedUser->id, false);
foreach ($usersGroups as $next_key => $nextUsersGroup) {
if (in_array($nextUsersGroup->group_id, $accessArray)) {
$condition = true;
}
}
}
return "<?php if ($condition) { ?>";
});
Blade::directive('endLoggedUserHasAccess', function () {
return "<?php } ?>";
});
But I got syntax error : https://imgur.com/a/I5s1TmQ
USER_ACCESS_ADMIN is defined in bootstrap/app.php.
looks like my syntax is invalid, but which is valid ?
Thanks!

How to use x-editable with CodeIgniter?

I would like to understand using x-editable in my CodeIgniter first project. I tried to read x-editable docs but I'm beginner in JavaScript too so I can't understand
I make simple controller to collect data from JavaScript but I didn't complete it or data not updated in database.
$('#username').editable({
type: 'text',
pk: 1,
url: '/post',
title: 'Enter username'
});
How to get submitted data in controller or model to process database update query
I want to passing data submitted from x-editable to model to update it in database.
You can follow this simple steps
Assume that $userId = 5 ; $username = "admin";
Consider you html look like this
<a type="text" name="username" onclick="setEditable(this);" data-pk="<?php echo $userId ;?>" data-placeholder="Enter Username" data-name="username" data-type="text" data-url="<?php echo site_url();?>user/updateUserName" data-value="<?php echo $username ;?>" data-prev="admin" data-title="Enter Username"><?php $username; ?></a>
In Javascript code write following
$.fn.editable.defaults.mode = 'inline';
function setEditable(obj) {
$(obj).editable({
emptytext: $(obj).attr('data-value'),
toggle: 'dblclick',
mode: 'inline',
anim: 200,
onblur: 'cancel',
validate: function(value) {
/*Add Ur validation logic and message here*/
if ($.trim(value) == '') {
return 'Username is required!';
}
},
params: function(params) {
/*originally params contain pk, name and value you can pass extra parameters from here if required */
//eg . params.active="false";
return params;
},
success: function(response, newValue) {
var result = $.parseJSON(response);
$(obj).parent().parent().find('.edit-box').show();
$(obj).attr('data-value', result.username);
$(obj).attr('data-prev', result.username);
},
error: function(response, newValue) {
$(obj).parent().parent().find('.edit-box').hide();
if (!response.success) {
return 'Service unavailable. Please try later.';
} else {
return response.msg;
}
},
display: function(value) {
/*If you want to truncate*/
var strName = strname !== '' ? strname : $(obj).attr('data-value');
var shortText = '';
if (strName.length > 16)
{
shortText = jQuery.trim(strName).substring(0, 14).split("").slice(0, -1).join("") + "...";
}
else {
shortText = strName;
}
$(this).text(shortText);
}
});
$(obj).editable('option', 'value', $(obj).attr('data-value'));
}
In Controller site
<?php
class User extends CI_Controller
{
function __construct()
{
parent::__construct();
}
function updateUserName()
{
$this->load->model('user_model');
if ($this->input->is_ajax_request()) {
$valueStr = $this->input->get_post('value') ? $this->input->get_post('value') : '';
$new_nameStr = trim($valueStr);
$result_arr['username'] = $new_nameStr;
$userId = $this->input->get_post('pk') ? $this->input->get_post('pk') : '';
$data['username'] = $new_nameStr;
$result_arr['username'] = $new_nameStr;
$this->user_model->userUpdateFunction($data, $userId);
}
echo json_encode($result_arr);
exit;
}
}
You can change editable mode , i have set inline only
First of all, this question is about AJAX and JavaScript/jQuery, not Codeigniter.
Basically, the code that you wrote is about posting data with AJAX. First, you need to create a controller and model, then you can post data with AJAX. I'm adding a sample code:
Controller file:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Sample extends CI_Controller {
function __construct() {
parent::__construct();
$this ->load ->model('modelfolder/sample_model');
}
public function index() {
$this->sample_model->sampleFunction();
}
}
Model File:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Sample_model extends CI_Model {
function sampleFunction() {
$data = array('fieldName' => $this->input->post('userName', TRUE));
$this->db->where('id', $this->input->post('userId', TRUE));
$this->db->update('tableName', $data);
return true;
}
}
routes.php File:
$route['demoPost'] = 'controller_folder/sample';
View File's HTML part:
<form id="sampleForm">
<input type="text" name="userId" />
<input type="text" name="userName" />
</form>
View File's AJAX part:
$(document).ready(function(){
$("#sampleForm").submit(
function(){
$.ajax({
type: "POST",
url: "<?php echo site_url('demoPost'); ?>",
data: $("#sampleForm").serialize(),
});
});
});

Routing to controller with optional parameters

I'd like to create a route that takes a required ID, and optional start and end dates ('Ymd'). If dates are omitted, they fall back to a default. (Say last 30 days) and call a controller....lets say 'path#index'
Route::get('/path/{id}/{start?}/{end?}', function($id, $start=null, $end=null)
{
if(!$start)
{
//set start
}
if(!$end)
{
//set end
}
// What is the syntax that goes here to call 'path#index' with $id, $start, and $end?
});
There is no way to call a controller from a Route:::get closure.
Use:
Route::get('/path/{id}/{start?}/{end?}', 'Controller#index');
and handle the parameters in the controller function:
public function index($id, $start = null, $end = null)
{
if (!$start) {
// set start
}
if (!$end) {
// set end
}
// do other stuff
}
This helped me simplify the optional routes parameters (From Laravel Docs):
Occasionally you may need to specify a route parameter, but make the presence of that route parameter optional. You may do so by placing a ? mark after the parameter name. Make sure to give the route's corresponding variable a default value:
Route::get('user/{name?}', function ($name = null) {
return $name;
});
Route::get('user/{name?}', function ($name = 'John') {
return $name;
});
Or if you have a controller call action in your routes then you could do this:
web.php
Route::get('user/{name?}', 'UsersController#index')->name('user.index');
userscontroller.php
public function index($name = 'John') {
// Do something here
}
I hope this helps someone simplify the optional parameters as it did me!
Laravel 5.6 Routing Parameters - Optional parameters
I would handle it with three paths:
Route::get('/path/{id}/{start}/{end}, ...);
Route::get('/path/{id}/{start}, ...);
Route::get('/path/{id}, ...);
Note the order - you want the full path checked first.
Route::get('user/{name?}', function ($name = null) {
return $name;
});
Find more details here (Laravel 7) : https://laravel.com/docs/7.x/routing#parameters-optional-parameters
You can call a controller action from a route closure like this:
Route::get('{slug}', function ($slug, Request $request) {
$app = app();
$locale = $app->getLocale();
// search for an offer with the given slug
$offer = \App\Offer::whereTranslation('slug', $slug, $locale)->first();
if($offer) {
$controller = $app->make(\App\Http\Controllers\OfferController::class);
return $controller->callAction('show', [$offer, $campaign = NULL]);
} else {
// if no offer is found, search for a campaign with the given slug
$campaign = \App\Campaign::whereTranslation('slug', $slug, $locale)->first();
if($campaign) {
$controller = $app->make(\App\Http\Controllers\CampaignController::class);
return $controller->callAction('show', [$campaign]);
}
}
throw new \Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
});
What I did was set the optional parameters as query parameters like so:
Example URL:
/getStuff/2019-08-27?type=0&color=red
Route:
Route::get('/getStuff/{date}','Stuff\StuffController#getStuff');
Controller:
public function getStuff($date)
{
// Optional parameters
$type = Input::get("type");
$color = Input::get("color");
}
Solution to your problem without much changes
Route::get('/path/{id}/{start?}/{end?}', function($id, $start=null, $end=null)
{
if(empty($start))
{
$start = Carbon::now()->subDays(30)->format('Y-m-d');
}
if(empty($end))
{
$end = Carbon::now()->subDays(30)->format('Y-m-d');
}
return App\Http\Controllers\HomeController::Path($id,$start,$end);
});
and then
class HomeController extends Controller
{
public static function Path($id, $start, $end)
{
return view('view');
}
}
now the optimal approach is
use App\Http\Controllers\HomeController;
Route::get('/path/{id}/{start?}/{end?}', [HomeController::class, 'Path']);
then
class HomeController extends Controller
{
public function Path(Request $request)
{
if(empty($start))
{
$start = Carbon::now()->subDays(30)->format('Y-m-d');
}
if(empty($end))
{
$end = Carbon::now()->subDays(30)->format('Y-m-d');
}
//your code
return view('view');
}
}

Ajax changing the entire sql query

http://rimi-classified.com/ad-list/west-bengal/kolkata/electronics-and-technology
The above link has a filter in the left. I am trying to use ajax to get city from state. but as the ajax is triggered the entire query is changing.
SELECT * FROM (`ri_ad_post`)
WHERE `state_slug` = 'west-bengal'
AND `city_slug` = 'kolkata'
AND `cat_slug` = 'pages'
AND `expiry_date` > '2014-03-21'
ORDER BY `id` DESC
It is taking the controller name in the query (controller name is pages).
The actual query is:
SELECT *
FROM (`ri_ad_post`)
WHERE `state_slug` = 'west-bengal'
AND `city_slug` = 'kolkata'
AND `cat_slug` = 'electronics-and-technology'
AND `expiry_date` > '2014-03-21'
ORDER BY `id` DESC
// Controller
public function ad_list($state,$city,$category,$sub_cat=FALSE)
{
if($state===NULL || $city===NULL || $category===NULL)
{
redirect(base_url());
}
$data['ad_list'] = $this->home_model->get_adlist($state,$city,$category,$sub_cat);
$this->load->view('templates/header1', $data);
$this->load->view('templates/search', $data);
$this->load->view('ad-list', $data);
$this->load->view('templates/footer', $data);
}
public function get_cities()
{
$state_id = $this->input->post('state');
echo $this->city_model->get_cities($state_id);
}
// Model
public function get_adlist($state,$city,$category,$sub_cat=FALSE)
{
if ($sub_cat === FALSE)
{
$this->db->where('state_slug', $state);
$this->db->where('city_slug', $city);
$this->db->where('cat_slug', $category);
$this->db->where('expiry_date >', date("Y-m-d"));
$this->db->order_by('id', 'DESC');
$query = $this->db->get('ad_post');
}
$this->db->where('state_slug', $state);
$this->db->where('city_slug', $city);
$this->db->where('cat_slug', $category);
$this->db->where('sub_cat_slug', $sub_cat);
$this->db->where('expiry_date >', date("Y-m-d"));
$this->db->order_by('id', 'DESC');
$query = $this->db->get('ad_post');
return $query->result_array();
//echo $this->db->last_query();
}
//ajax
<script type="text/javascript">
$(document).ready(function () {
$('#state_id').change(function () {
var selState = $(this).val();
alert(selState);
console.log(selState);
$.ajax({
url: "pages/get_cities",
async: false,
type: "POST",
data : "state="+selState,
dataType: "html",
success: function(data) {
$('#city').html(data);
$("#location_id").html("<option value=''>--Select location--</option>");
}
})
});
});
</script>
Please help me how to solve this issue. Please check the url I have provided and try to select a state from the filter section the problem will be more clear.
In .js what is the value of selState ?
In your model, you should if() else() instead of just a if, because your query will get override.
Where is the get_cities function ? Can we see it ?
On your url, the problem is that your ajax url doesn't return a real ajax call but an entire HTML page which is "harder" to work with. Try to change it into json (for dataType's ajax()) You should only do in your php something like this :
in your controller :
public function get_cities()
{
$state = $this->input->post('state');
//Do the same for $cat
if (!$state) {
echo json_encode(array('error' => 'no state selected'));
return 0;
}
$get_cities = $this->model_something->getCitiesByStateName($state);
echo json_encode($get_cities);
}
You should definitely send with ajax the $cat info

Resources