Laravel 8 string between function doesn't work properly - laravel

When using the Str::between function from Laravel 8, it jumps over the first occurrence of the 'TO' variable. Is there something wrong I'm doing, or is it broken?
<span class="website-title">Name</span> All Rights Reserved.</p>';
$slice = Str::between($string, '<span class="current-year">', '</span>');
Returns '2022 Name' when it should only return '2022.'

I think it finds the last occurrence of the last parameter in the between method. To solve this, you could do something like
$slice = Str::between($string,
'<span class="current-year">',
'</span> <span class="website-title">');

Related

Last element of an array in Thymeleaf

How can I know if the current iteration is the last one?
<th:block th:each="err: ${#fields.errors('confirmedPassword')}">
[[${err}]],
</th:block>
As you can see, a comma will be placed after each error message. However, I would like to place a full stop after the last iteration instead.
This worked for me:
<th:block th:each="errMsg, errStatus: ${#fields.errors('confirmedPassword')}">
<th:block th:text="!${errStatus.last} ? ${errMsg} + ', ' : ${errMsg} + '.'"></th:block>
</th:block>
You can use the iteration status variable for this. It has a property last that is set to true on the last iteration. Something like this should work:
<th:block th:each="err, status: ${#fields.errors('confirmedPassword')}">
[[${err}]][# th:unless="${status.last}"],[/]
</th:block>

Format phone number in Laravel Blade

Is there a simple way to format a phone string for display in a Laravel Blade template?
I am trying to take '612345678'
and insert it as {{ $user{'phone'] }} and have it display as 612 345 678
Feel free to use the following package:
https://github.com/Propaganistas/Laravel-Phone
and use it for example:
{{ phone('612345678'); }}
{{ phone($user['phone'], 'US'); }}
add the function in the model
public function phoneNumber() {
// add logic to correctly format number here
// a more robust ways would be to use a regular expression
return "(".substr($data, 0, 3).") ".substr($data, 3, 3)." ".substr($data,6);
}
and display it into your blade as
{{ $user->phoneNumber() }}
This will give you (###) ###-####
preg_replace('~.*(\d{3})[^\d]{0,7}(\d{3})[^\d]{0,7}(\d{4}).*~', '($1) $2-$3', $simple->phone)
You can try this:
$format = chunk_split($user['phone'], 3, ' ');
You will get your phone number as "612 345 678 " with a space trailing behind.
To remove the last space trailing behind, you can use rtrim() function.
rtrim($format, ' ');
Hope this works.

Best practice in laravel blade use of {{ }}

Which of those two is the best practice using blade in laravel:
<p>{{ $person->name }} {{ $person->surname }}</p> or <p>{{ $person->name . ' ' . $person->surname }}</p>
Thanks!
Neither is a good option because in case one is empty (first or last name) - you will have an extra space that doesn't mean anything.
Best practises are:
1) Implement a method like getName() on your Person class that does the concatenation for you. Eg.
public function getName()
{
return implode(' ', array_filter([$this->name, $this->surname])));
}
And in your template it would become just <p>{{ $person->getName() }}</p>
2) If you have more attributes that require alteration before rendering - a common practise is to extract them all to a presenter class (that's a design pattern). Then your template would look like <p>{{ $person->presenter()->getName() }}</p>. But if it's just the name - you are probably fine just keeping it in the Person class.
It's usually all down to personal preference, Both are perfectly valid ways to do it, I like keeping everything seperate because at least for me (not everyone might think this is easier/cleaner), it becomes so much easier to add extra markup like this;
<b>{{ $person->surname }}</b>, <small class='text-muted'>{{ $person->name }}</small>
I always like to think of it in terms of dumb days, if you're having one of those days where you just can't think, which is easier to read for you :)

preg_match_all skippes one nested tag

if you look at this tag:
$text = '<div class="inner">
<div class="left">
<h4>text </h4>
<p>Abdijstreet 42b<br>2000 city </p>
</div>
<div class="right">
<span class="red">10:00 - 14:00</span>
</div>
</div>'
I use this to preg_match:
preg_match_all("'<div class=\"inner\">(.*?)</div>'si", $text, $match); // de ul tags
$match[1] = array_splice($match[0], 0);
foreach($match[1] as $val) // hele pagina
{
echo $val;
}
Well i tried many things, but i only get whats between and never what i need for , what am i doing wrong?
Are you trying to get everything between the beginning and ending div tags? If so, then you're really close. All you'd need to do is just remove the question mark ? from your expression. The question mark tells the script to stop matching once it finds the next item in the REGEX. In this case, the next item is a closing div tag. So once it finds it, it stops. If you leave it out, it will keep matching until it hits the last div tag it can find.
$text = '<div class="inner">
<div class="left">
<h4>text </h4>
<p>Abdijstreet 42b<br>2000 city </p>
</div>
<div class="right">
<span class="red">10:00 - 14:00</span>
</div>
</div>';
preg_match_all("'<div class=\"inner\">(.*)</div>'si", $text, $match);
print "<pre><font color=red>"; print_r($match); print "</font></pre>";
If you're trying to pull out each item in a div, then you'd probably want to consider using DOM instead of REGEX to tackle this problem. But since you used the preg-match tag, then here it is in REGEX:
preg_match_all('~<div class="(?!inner).*?>\K(.*?)(?=</div>)~ims', $text, $matches);
print "<PRE><FONT COLOR=BLUE>"; print_r($matches[1]); print "</FONT></PRE>";
That gives you this:
Array
(
[0] =>
<h4>text </h4>
<p>Abdijstreet 42b<br>2000 city </p>
[1] =>
<span class="red">10:00 - 14:00</span>
)
Explanation of the REGEX:
<div class=" (?!inner) .*? > \K (.*?) (?=</div>)
^ ^ ^ ^ ^ ^ ^
1 2 3 4 5 6 7
<div class=" Look for a literal opening div tag <div, followed by a space, followed by the word class, followed by an equal sign, followed by a quotation mark.
(?!inner) This is a negative lookahead (?!) that makes sure the word inner is not coming up next.
.*? Matches any one character ., zero or more times *, all the way up until it hits the next item in our regular expression ?. In this case, it will stop once it finds a closing HTML bracket.
> Find a closing HTML bracket.
\K This tells the expression to forget everything it has matched so far and start matching again from here. This basically makes sure that the first part of the expression is there, but does not store it for us to work with.
(.*?) Same as number 3, except we use parenthesis () around it so we can capture it and do something with it later.
(?=</div>) This is a positive lookahead (?=) that makes sure the closing div tag </div> is coming up at the end of the expression, but does not capture it.
Here is a working demo of the code above

Standard Pattern for Iterating Over Loop and Printing Start and End Tags

This is a problem I have run into before and I have yet to find an elegant solution, so I thought I would ask for SO's help.
I am iterating through an array and printing off some information from that array and having trouble figuring out how to print my start and end <div> tags. Below is an example table and the desired output along with a basic implementation of my current algorithm. I am hoping that somebody can point me to a better algorithm for printing the data. I'm doing it in PHP, but a generic algorithm would be wonderful.
Thanks very much!
Table: (spacing added for clarity)
Choice ID Choice Body Question ID Question Body
---------------------------------------------------------------------
1 Yes, very much 1 Do you like sandwiches?
2 Somewhat 1 Do you like sandwiches?
3 Not at all 1 Do you like sandwiches?
4 I hate them 1 Do you like sandwiches?
5 Sure, why not 2 Do you like apples?
6 Yesh, I guess 2 Do you like apples?
7 What are those 2 Do you like apples?
8 Yes, very much 3 Do you like chips?
9 Not at all 3 Do you like chips?
Desired Output:
<div class='question' id='1'>
<p>Do you like sandwiches?</p>
<div class='choices'>
<span class='choice'>Yes, very much</span>
<span class='choice'>Somewhat</span>
<span class='choice'>Not at all</span>
<span class='choice'>I hate them</span>
</div>
</div>
<div class='question' id='2'>
<p>Do you like apples?</p>
<div class='choices'>
<span class='choice'>Sure, why not</span>
<span class='choice'>Yeah, I guess</span>
<span class='choice'>What are those</span>
</div>
</div>
<div class='question' id='3'>
<p>Do you like chips?</p>
<div class='choices'>
<span class='choice'>Yes, very much</span>
<span class='choice'>Not at all</span>
</div>
</div>
Basic Algorithm I'm Currently Using:
$last_id = null;
while ($choice = pg_fetch_array($choices)) {
if ($last_id != $choice['id']) {
if ($last_id != null) {
echo "</div>";
}
echo "<div id='$choice[id]'>";
}
// Print choice info
$last_id = $choice['id'];
}
if ($last_id != null) {
echo "</div>";
}
Note: The reason I'm using this way is for optimization purposes. This requires only one database query, and there are going to be a lot of results. I don't want to have to do a query for each question to get it's choices. I know how to do that, and it is easier, but not very efficient or fast.
Edit 1: Fixed code, the algorithm now works, but still isn't pretty. For the commenter: pg_fetch_array() is a PostgreSQL function that basically creates an associative array. Very similar to an object. Allows you to just ask for the $choice['id'] or $choice['body'].
Grouping items by similar values can hardly be called an algorithm. It's more of a coding pattern if anything else.
A good way to code is to separate the mechanism from the intent. In this case the mechanism is how to keep track of the key values to find the grouping boundaries and the intent is to output HTML for each sequential group.
Python for instance has a library function called groupby to do exactly this. So in Python the code would look something like this (ignoring the fact that one would use a templating library for this):
from itertools import groupby
def question_from_row(row):
return dict(id=row['question_id'], body=row['question_body'])
for question, choices in groupby(questions, key=question_from_row):
print('<div class="question" id="%s">' % question['id'])
print(' <p>%s</p>\n' % question['body'])
print(' <div class="choices">')
for choice in choices:
print('<span class="choice">%s</span>' % choice['choice_body'])
print(' </div>')
print('</div>')
PHP to my knowledge doesn't have anything like that built in, but a naive implementation is pretty easy:
function array_groupby($input, $keyfunc) {
$output = array();
$last_key = null;
$current = null;
foreach ($input as $item) {
$item_key = $keyfunc($item);
if ($last_key === null || $item_key != $last_key) {
if ($current !== null) {
$output[] = $current;
}
$last_key = $item_key;
$current = array();
}
$current[] = $item;
}
if ($current !== null) {
$output[] = $current;
}
return $output;
}
This would be typical library code that you include in. The code that deals with the output then becomes rather trivial. Completely isolated from how the grouping is done. For instance you could change array_groupby to return an object that implements the Iterator interface and only lazily fetches from the input iterable.
$questions = array_groupby(pg_fetch_array($choices),
function($choice) { return $choice['id']; });
foreach ($questions as $choices) {
$question = $choices[0];
echo '<div class="question" id="'.$question['id'].'">';
echo '<p>'.$question['body'].'</p>';
echo '<div class="choices">';
foreach ($choices as $choice) {
echo '<span class="choice">'.$choice['choice_body'].'</span>';
}
echo '</div>';
echo '</div>';
}
This example is using the PHP 5.3 closures feature. On older versions specifying the function to extract the grouping key would be slightly uglier, perhaps calling for an object oriented approach.
You should print the closing </div> at the beginning of the loop, if the freshly read id is different from last one (and the last one is not null).
Additionally, after the loop (again, if last id is not null, which would mean that there were no groups at all) you need to close the last group.
Been a while since I've done any PHP but I'd try something like this...
// print leading div for very first in array
echo "<div>";
$last_question = null;
while ($choice = pg_fetch_array($choices)) {
// print choice info
echo "<span ...>";
if($last_question != $choice['question_id'])
{
// print trailing div for last one
echo "</div>";
// print leading div for next one
echo "<div>";
}
// set last question
$last_question = $choice['question_id'];
}
// print trailing div for very last in array
echo "</div>";
Might need improving to make sure it doesn't print an extra div at the end.

Resources