ohffs

Experience

248,720

276 Best Reply Awards

  • Member Since 3 Years Ago
  • 929 Lessons Completed
  • 2 Favorites

20th July, 2018

ohffs left a reply on Docker Series • 1 day ago

@fideloper cheers :-) I'm currently swearing at kubernetes - the docs are really thorough, but strangely unhelpful ;-) thanks again for the original docker series - it's got me 90% of the way there. I think! ;-)

12th July, 2018

ohffs left a reply on Docker Series • 1 week ago

@fideloper sorry for the rando-ping - just wondering if you've any plans to do either an addendum or a further series on the 'shipping docker' videos? I found it immensely useful but I'm now kind of at what would have been the next chapter in the series I guess - trying to figure out a lot of production decisions which possibly you've already been through :-) Currently at the swarm+traefik+keepalived stage and thinking to myself 'this seems to be working, but what have I overlooked...' or 'is swarm going to be around in a year, should I just suffer the pain of kubernetes?' :-) Self doubt ftw :-D

ohffs left a reply on Desperate For Ideas On Possible Design Patterns • 1 week ago

@cr0nwell Laravel includes the Symfony Process Package which is probably the nicest way to call out to python from a job.

ohffs left a reply on How To Change Redis Keys Initial? • 1 week ago

I think it's the prefix value in config/cache.php. You might be better using a different redis database ID for each app though if you really want to keep things separate - it's in the config/database.php redis section.

11th July, 2018

ohffs left a reply on This Site Can’t Be Reached On Production Server After Client Made Changes Via SSH • 1 week ago

No worries - we've all been in similar situations sometime :-) Hope you get it all sorted :-)

ohffs left a reply on This Site Can’t Be Reached On Production Server After Client Made Changes Via SSH • 1 week ago

I don't use forge, but yeah - I think it defaults to nginx. Maybe some people more familiar with forge can chip in - but if I was you I think I'd start work on the new droplet anyway and go wrap your clients knuckles - I hope you get to charge them some extra money too! :-)

ohffs left a reply on Desperate For Ideas On Possible Design Patterns • 1 week ago

If you're scraping html - it might be worth your while having a quick look at scrapy. It's python rather than php, but it'll probably do what you need - you can always run it from a laravel queue if your more familiar with that.

ohffs left a reply on This Site Can’t Be Reached On Production Server After Client Made Changes Via SSH • 1 week ago

The 'runcloud' part is possibly what's broken things - I think (from a brief look at their website) it seems to do some kind of server magic so possibly has broken what forge had done to the server :-/ Purely a guess though. Try running nginx -t (you might need to run sudo nginx -t) and see if it can find it's config file and test it's valid - but if the runcloud thing has reconfigured your server you might be better off trying to bring up a copy of the site on another droplet rather than un-do whatever it's done - just make sure you copy any files/db's though :-)

Edit: ah, just noticed @Nash said much the same :-) I am a slow typer today ;-)

ohffs left a reply on This Site Can’t Be Reached On Production Server After Client Made Changes Via SSH • 1 week ago

Is the webserver (apache/nginx/whatever) still running on the server? You should be able to run pgrep apache (or 'httpd' or 'nginx' or 'php-fpm'). If it is, maybe try doing a curl localhost and see if it's reachable from inside the server - then check if there's a firewall blocking remote things (iptables --list --numeric) - if that gives a lot of output then you could try opening up port 80/443 (I think you can do that via forge).

9th July, 2018

ohffs started a new conversation OAuth Login Via Passport/Ldap Backend • 1 week ago

'Allo all,

Most of my apps use LDAP to authenticate the user against our organisations LDAP server - which is fine. But the LDAP server is only available to local networks so if we look to a future where we might offload some of the server/hosting to Azure/AWS/Google I'd lose the ability to authenticate users with their regular accounts.

So - I thought I'd just use Passport to act as an OAuth server (using the LDAP server) and let the remote client apps use that via socialite. But it looks like Passport doesn't have a built-in provider for Socialite? Which seems.... odd? There's a 3rd-party provider - but it doesn't fill me with confidence that the github repo is currently saying it's not maintained.

Anyway - I'm only vaguely familiar with OAuth (this project was going to let me learn more about it) but it feels like I'm already on shaky ground. Am I getting it totally wrong that the two official Laravel OAuth packages don't talk to each other?

6th July, 2018

ohffs left a reply on Ensuring That There Are Tests For A Given Set Of Classes (static Analysis?) • 2 weeks ago

This package from Spatie might be of help for the content/data checking?

https://github.com/spatie/phpunit-snapshot-assertions

To ensure there are tests for each resource is a bit of a rabbit-hole I think. You could write a script or artisan command which looped over all of the files in app/Http//Resources/ and complained (or created) a missing matching test in tests/Api/Resources/ or something - but then you need to remember to run it, so you need a test to test that you've run your script to make your tests ;-)

Or I guess you could add an artisan command like 'make:tested-resource' which itself called 'make:resource' and 'make:test' - but then you need to remember to run that rather than 'make:resource', so you're back to just having to remember to do it :-)

20th June, 2018

ohffs left a reply on RefreshDatabase Trait Doesn't Refresh Database • 1 month ago

@ew-stefan this is plain old http/unit tests - no dusk. It's quite puzzling - a few other people have mentioned the same thing happening to them. Using DatabaseMigrations works ok - it just seems to be the RefreshDatabase trait that's showing the issue.

15th June, 2018

ohffs left a reply on Disabling The Csrf For The Login POST Route • 1 month ago

@click yeah - that was something I originally tried, but I think my users are letting their device go to sleep, waking it up and pressing submit right away - so not much gets the chance to refresh/reload before they do it.

Users will always thwart you :-)

ohffs left a reply on RefreshDatabase Trait Doesn't Refresh Database • 1 month ago

Oddly enough - this has started happening to me today. I've got the RefreshDatabase trait in place - but the tests still seem to leave data kicking around between tests if I use the mysql driver (sqlite in-memory and on-disk are fine).

If I comment out the lines in the trait as the OP had - the tests run fine. If I call $this->refreshDatabase() in the test it doesn't help - but running Model::truncate() does.

It's really quite annoying as it's making all my CI/Staging tests fail and the code that worked ok is one commit behind a huge monolithic one (yeah, I know - but it was seemingly innocent and just added lots of event() calls and everything was passed using the local sqlite tests).

Is anyone else hitting this just now, or is it just a co-incidence I'm seeing this pop up again? It's been a long Friday, so I've probably just broken something obscure... :-/

ohffs left a reply on Disabling The Csrf For The Login POST Route • 1 month ago

Thanks for the replies, @Snapey @click & @Cronix :-) I've already got a little JS script that keeps the token 'alive' for both _token fields and the axios/ajax one - I was just hoping to avoid having to hook it into every app - especially as it's really just the login page my users seem to leave open.

But I guess (lazy sigh!) it's best to keep csrf in general. If I can pluck up the energy maybe I'll pull the token refresh script in next time I'm doing a laravel version bump and have to re-visit all the apps anyway :-)

Thanks again - much appreciated :-)

14th June, 2018

ohffs left a reply on Disabling The Csrf For The Login POST Route • 1 month ago

@36864 usually to make an authenticated user do something they didn't mean to - you don't 'get' anything as the 'bad user' as you're not logged in. The first memories I have of seeing it was people posting a javascript 'logout' link to forums as if it was an innocent link to google or whatever - but they were innocent days ;-)

I should have pointed out that none of these apps are open to user registration - so it's only people who already have accounts who can log in.

I think the only potential problem I can see is one 'bad' user somehow creating a form which submitted their own login details to the form from a different server and tricking a 'good' user to submit it, then... I don't know.

ohffs left a reply on Disabling The Csrf For The Login POST Route • 1 month ago

@36864 I think if a 'bad user' was to hit the login route again (it's only the POST I'm targetting) they'd still need a valid session set when they did the request - otherwise they'd follow the normal credentials check against the username/password. If they've already got the ability to either login or generate a valid session then I've got much bigger problems ;-)

I may well be wrong though and am just looking for an excuse to take the easy route ;-)

ohffs left a reply on Disabling The Csrf For The Login POST Route • 1 month ago

@arukomp sadly, I've already done that and they ignore the message :-/

ohffs started a new conversation Disabling The Csrf For The Login POST Route • 1 month ago

Seemingly, I've got a lot of users across multiple apps who get as far as the login page, leave it open for a long time then try and submit. At which point they hit the csrf middleware and are left confused.

I'm trying to think if it would be 'ok' to disable csrf on just the login route to cut down on the number of 'the website doesn't work!' messages I get every day. Part of me is thinking 'no! bad!' and (I admit, the lazy) part of me is thinking 'but is it really?'.

I know I could work around it with various js-esque refresh calls, but apart from the hassle, they don't seem to help much with the 'let the laptop/phone go to sleep for four hours, then press submit' problems I'm seeing.

Anyway - does anyone have a glaring 'omg!' reason I shouldn't do it?

7th June, 2018

ohffs left a reply on Tips For Web Application With 3 Roles • 1 month ago

If your roles are quite small in number - you might be better starting out by just having some flags on the user models like 'is_admin', 'is_superadmin'. You can always change over to 'full fat' roles & permissions later if you need.

But if you need more complicated roles & permissions from the start, maybe have a look at bouncer or spatie's package which will take care of a lot of it for you.

2nd June, 2018

ohffs left a reply on Drag And Drop Between 2 Divs With JQuery's Draggable • 1 month ago

If you're not 100% tied to the jquery - the draggable library from shopify is really easy to use. Might be worth a quick look :-)

5th May, 2018

ohffs left a reply on Getting The Json Data For An API Resource • 2 months ago

ah, so that's what API's are - I've always wondered.... o_O

ohffs left a reply on Getting The Json Data For An API Resource • 2 months ago

:: one-off bump :: :-)

3rd May, 2018

ohffs started a new conversation Getting The Json Data For An API Resource • 2 months ago

'Allo,

I've got a bit of code for an API that uses the Laravel API resources. I'd quite like to re-use the same logic/code in a different place for consistancy. But I can't see an obvious way of getting the resulting JSON data out of the Resource object.

So I have a resource a bit like :

return [
    'username' => $this->username,
    'surname' => $this->surname,
    'forenames' => $this->forenames,
    'email' => $this->email,
    'created' => $this->created_at->format('Y-m-d H:i'),
    'updated' => $this->updated_at->format('Y-m-d H:i'),
    'projects' => Project::collection($this->projects),
];

The only way I've found to do it and have it fully build the resource is to do :

json_decode(
    (new UserResource($user))->toResponse($this)->getContent()
)

Which is a bit ugly to say the least. I've tried the more obvious-sounding method :

(new UserResource($user))->jsonSerialize()

But that only transforms the 'top level' part, not the included related 'Project' collection. Anyone have any pointers? :-)

28th April, 2018

ohffs left a reply on Can Some Review My Code And See How I'm Doing - Users Adding Eachother In Laravel • 2 months ago

I'd just put it on the model for now :-) You just put the same login in there (well, replace $Tenancy with $this)- you're just giving it an easy to read name :-) But you wouldn't have the code to render the button in there - that can stay in the view. Eg, on your Tenancy mode :

public function hasPendingRequest()
{
    return $this->accepted == 0 && $this->request_sent == 1;
}

Then in your view you would just do the @if (...) <render the button> @endif.

To avoid having to check if the Tenancy is null, you can just pass a new one to your view too. Eg, in the create method you could do :

public function create($id){
    $user = User::where('id', $id)->first();
    $properties = PropertyAdvert::where('user_id', Auth::id())->get();
    $tenancy = new Tenancy;

    return view('/pages/account/tenancy/create', compact('user', 'properties', 'tenancy'));
}

Give it a try anyway and see if you think it looks/feels nicer :-)

ohffs left a reply on Can Some Review My Code And See How I'm Doing - Users Adding Eachother In Laravel • 2 months ago

One thing that leaps out at me that would be a quick 'win' would be to replace some of those long boolean conditionals in your view and give them helpful names. For instance

@if($Tenancy != null && $Tenancy->accepted == 0 && $Tenancy->request_sent == 1)

could be :

@if ($tenancy->hasPendingRequest())

That kind of thing anyway - it makes it easier on yourself when you come back to change the code in a year ;-)

You might also be better splitting your view (and likely controller) into two different versions - one for the tenant and one for the landlord - that way you have a lot less to worry about and check with 'if' statements.

Other than that - you seem to be mixing bits of code that I don't quite understand. For instance in your 'create' method you have :

    $user = User::where('id', $id)->first();
    $properties = PropertyAdvert::where('user_id', Auth::id())->get();

So you are getting the properties for the authenticated user, but the '$user' you are passing to the view could be someone else? I'm not sure if that's a feature of your site or just an accident :-)

Then in your accept/reject methods you are updating the database based on the 'accepted' and 'request_sent' flags, but not to a specific Tenancy id? So it looks like it would update potentially a lot of un-related rows in the table?

Anyway - hope some of that is helpful :-)

21st April, 2018

ohffs left a reply on Apache Monitor Tool (recommendations) • 3 months ago

Munin, Zabbix and Prometheus are quite popular. Depends what you're wanting to 'monitor' though - you could end up with something using logstash and kibana.

You're not short of options really depending how much insight & details you want and the scale of what you're doing :-)

20th April, 2018

ohffs left a reply on Upgrading Legacy Project V5.2.39 • 3 months ago

Exactly how much of a pain it will be depends a lot on the project. I seem to remember 5.2 -> 5.3 was a bit annoying, but after that it has been fairly painless for my own projects at least. A lot will depend on whether the code uses much in the way of 'undocumented' or 'out of the way' features - and also if you want to change the code to take advantage of new features in Laravel or just 'get it working'

If you have any kind of budget available maybe have a look at https://laravelshift.com/ which can automate a lot of the 'grunt work' :-)

9th April, 2018

ohffs left a reply on Introducing Laravel Fast Excel • 3 months ago

@jlrdw I've got a non-framework-specific basic excel wrapper at : https://github.com/ohnotnow/simple-spout that uses the same underlying 'spout' fast excel library - still uses composer though I'm afraid :-/ But if you install it via composer you should (I think!) just be able to do :

require_once('./vendor/autoload.php');
$data = (new \Ohffs\SimpleSpout\ExcelSheet)->import('/path/to/whatever.xlsx');

28th March, 2018

ohffs started a new conversation Gitlab/CI - Compling Assets • 3 months ago

'Allo,

I've used gitlab quite a lot for the testing side of things (ie, push to repo - gitlab spins up a test runner and tells me if it's broken). But I'd quite like to move to eventually deploying using gitlab/docker too.

One thing that's not very clear to me is where I could add some kind of stage/job that would run 'npm run production' to compile/optimise the projects js/css and have that as part of the deployment without having to have node/npm on the actual server. Once or twice we've had projects pushed out to production where someone has commited the js/css in development mode so it would be really nice to eliminate that manual 'remember to run npm run prod before you commit to master' step.

I think I might want to use the assets part of the gitlab setup, but I'm not entrely sure. Anyone else done this?

14th March, 2018

ohffs left a reply on Laravel Forces Use Of Constructer Like This '__construct'. Wondering Why? • 4 months ago

Just to re-iterate what @martinbean said - the old style constructors should be replaced with the new __construct ones. Pretty much all current PHP code will assume that is how things are done. In the next major release of PHP the old style constructors will be removed altogether - from the PHP docs :

Warning: Old style constructors are DEPRECATED in PHP 7.0, and will be removed in a future version. You should always use __construct() in new code.

So although if the code works for now in 'pure' PHP 5.x/7.x - things like laravel and some other projects will fail - and when you update to a newer PHP version your code will stop working full stop no matter if you are using Laravel or not.

9th March, 2018

ohffs left a reply on MySQL Database Backup As A Service • 4 months ago

I seem to remember ottomatik getting some praise from some Laravel people a while back. I've never tried it myself though.

8th March, 2018

ohffs left a reply on Is There A Way To Run Horizon With Systemd? • 4 months ago

Just add a systemd unit file to (afair) /lib/systemd/system/. So something like horizon.service :

[Unit]
Description=Laravel Horizon Queue Manager
After=network.target auditd.service

[Service]
ExecStart=/usr/bin/php /path/to/your/artisan horizon
Restart=always

[Install]
WantedBy=multi-user.target

Might do the tricky anyway. You'll need to run systemctl enable horizon.service and systemctl start horizon.service - see if it works :-)

7th March, 2018

ohffs left a reply on Do You Randomize Uploaded Images Names Or Tie Them To Meaningful IDs? • 4 months ago

I tend to try and split up files a bit. Mostly to save a single directory ending up with 1000's & thousands of files which can make things quite slow. But that's only a concern if you're letting people upload/change lots of file. But yeah - you need to be a bit careful tying to specific user/category/whatever id's. Maybe you could just do a basic separation like :

/front/$random_filename
/side/$random_filename
/back/$random_filename

I guess it depends on how likely you think it is the category_id etc might change though (or any other random thing you might get asked to do down the line!). It's nice being able to do something like :

/front/2/3/image.jpg

Then from a filesystem level and your app level it's easy to know the file. Especially handy if a user says 'can I have yesterdays file back?' without needing to dig into the db as much to figure out filenames :-)

1st March, 2018

ohffs left a reply on Learning Testing - Using Classes With Dependency Injection • 4 months ago

Yay - glad it worked :-) Good luck with the rest of your testing! :-)

ohffs left a reply on Learning Testing - Using Classes With Dependency Injection • 4 months ago

If you replace new Cart(new SessionManager, new Dispatcher); with app(Cart::class) - does that help? That should ask laravel to recursively resolve all the dependencies if it can.

ohffs left a reply on MAC Addresses On LAN • 4 months ago

Ontop of what @crnkovic says, you could also run arpwatch on your server - then you can parse the file it logs (default is usually /var/lib/arpwatch/arp.dat) - saves doing a shell_exec :-)

28th February, 2018

ohffs left a reply on Design A Requirement Column For Course Table [Database] • 4 months ago

"It depends". You could just store it as text and print it out on the page, you could have a generic 'requirements' table and a pivot table like 'course_requirements' that joined it to the courses table or... other ways. 'It depends' :-)

ohffs left a reply on Download Large File From S3 *kind Of* Working • 4 months ago

No worries - glad you got it working :-)

ohffs left a reply on Download Large File From S3 *kind Of* Working • 4 months ago

If you remove the 'button' element altogether and put the class="btn btn-primary" on the <a> tag - does that help?

17th February, 2018

ohffs left a reply on Is There Anything Wrong With Calling Two Gates In Succession, Using ->authorize()? • 5 months ago

I don't think there's anything particularly wrong with it, personally. If you're having to do it in a few places maybe add an extra method/trait to the App\Http\Controllers\Controller so you could do :

$this->authorizes('is-coordinator', 'coordinators-can-deploy');

Maybe :-)

14th February, 2018

ohffs left a reply on RSA Encryption • 5 months ago

libsodium is now part of php 7.2 which gives you a whole lot of nice crypto stuff : https://secure.php.net/manual/en/book.sodium.php . You can hopefully just wrap some of that to do what you need?

ohffs left a reply on How To Reduce Model Data (eager Load) To One Field? • 5 months ago

Maybe have a look at the [pluck function)[https://laravel.com/docs/5.6/collections#method-pluck]?

9th February, 2018

ohffs left a reply on View Name Case Sensitive Problem Inside Sub-directory In Ubuntu 16.04 • 5 months ago

Rename the folder from Home to home?

8th February, 2018

ohffs left a reply on Queued Job - Best Way To Wait For An External Event • 5 months ago

@martinbean not really :-( it's being done by a regular torrent client (transmission) so I can only interact with it via it's http api. So I could theoretically have some kind of scheduled task which polled the torrent api - but it's much, much more 'expensive' to do that (circa 30seconds per run on the little rpi and ramps up it's CPU) and I'm still left running a scheduled task anyway.

I might look into extending the job class and see if there's a way I could do a '->releaseWithoutIncreasingTheRetryCount()' kinda thing as that's what I'm really after. I had kind of naively thought there must be a built in way to do a 'queue job, but only run on this condition' facility - but then again, I've never needed it until now so maybe it's not that common ;-)

ohffs started a new conversation Queued Job - Best Way To Wait For An External Event • 5 months ago

I've got a little (well, it was supposed to be little) home project to monitor torrent downloads and then let you copy them to another device. At the moment I just check in once in a while to see if a torrent has downloaded then I can click 'copy' and it kicks off a queued job which takes care of it in the background. All works fine.

But what I'd like to do is be able to think 'oh, that torrent is going to be a while' and click 'copy' and have it start copying when the torrent finishes downloading.

My first try was a simple check in the job itself to say 'if the torrent is still downloading, $this->release()' so the job would re-queue. But that fails quite a lot as the maximum retries can be hit very easily.

So I was wondering if there's a better way of doing it? The torrents are downloading via a 3rd-party program so I can't make that do much to help me.

My current hacky thought is to add (yet another!) flag onto the torrent entry in my apps db, so if I click 'copy' and it's still downloading then I set a 'auto_copy' flag to true - then there is a scheduled task that runs once in a while and it fires the background copy job off if the torrent has now downloaded. I don't always want the torrent to automatically copy btw, sometimes there isn't enough storage or it'll max out the raspberry pi I'm copying to.

But it feels like there should be a cleaner way than that - anyone run into this kind of situation?

ohffs left a reply on Collections 'where' And Pivot Values • 5 months ago

@bobbybouwmann pivot.choice was indeed the correct incantation :-) thank you :-D

3rd February, 2018

ohffs left a reply on Am I Refactoring The Right Way ? • 5 months ago

You could look into using Laravels authorization facilities too. Then you could end up with code that looked like :

public function destroy(Quote $quote)
{
  if (auth()->user()->cannot('delete', $quote) {
    // redirect with error message
  }
  $quote->delete();
  // return redirect... with success message
}

Or if you can be a little more 'brutal' (in the case the user should only ever get the option to delete something if it's theirs already, for instance - so this is a user deliberately doing something bad)

public function destroy(Quote $quote)
{
  $this->authorize('delete', $quote);  // that will return with a 403 if they are forbidden
  $quote->delete();
  // return redirect with success message
}

Using the authorization facilities can be nice as you can re-use them elsewhere. For instance in your blade template you can do :

@can('delete', $quote)
  <button>Delete</button>
@endcan

2nd February, 2018

ohffs left a reply on Collections 'where' And Pivot Values • 5 months ago

@bobbybouwmann ahhhh - that rings a bell now! Sadly I left work and didn't push that bit of code up to git (yes, I'm bad...) so I can't pull it down now to check - but I'll give it a try next week and mark this as correct if it works :-) Now that I see it written down it looks like what I was thinking before I did the 'pivot_choice' then sat thinking 'hrm, that's right, .... isn't it?' ;-) Thanks! Hope you have a good weekend :-)

ohffs started a new conversation Collections 'where' And Pivot Values • 5 months ago

I'm sure I've done this before, but it's reached that stage of a Friday afternoon where my brain has given up and google isn't helping much...

I've got a couple of many-to-many relations and a pivot table with some extra attributes. I'm including those in the relations using ->withPivot(...) as per - all works fine. But in another section of the code I need check based on the pivot table 'choice' column to do something like :

if ($projects->where('pivot_choice', 1)->isNotEmpty()) {
...

Which I'm sure used to work. but doesn't ;-) The curious thing is when I dd() the $projects to check they had the 'pivot_choice' field I can see :

#original: array:13 [
        "id" => "2"
        "title" => "Optio."
        "staff_id" => "3"
        "pre_req" => "Omnis voluptatibus ut facere."
        "description" => "Et est perspiciatis autem."
        "max_students" => "4"
        "created_at" => "2018-02-02 14:53:34"
        "updated_at" => "2018-02-02 14:53:34"
        "pivot_student_id" => "5"
        "pivot_project_id" => "2"
        "pivot_choice" => "2"
        "pivot_is_accepted" => "0"
      ]

#attributes: array:9 [
        "id" => "2"
        "title" => "Optio."
        "staff_id" => "3"
        "pre_req" => "Omnis voluptatibus ut facere."
        "description" => "Et est perspiciatis autem."
        "max_students" => "4"
        "created_at" => "2018-02-02 14:53:34"
        "updated_at" => "2018-02-02 14:53:34"
      ]

So the 'original' section has the pivot_ keys, but not the 'attributes' section - which is why I guess it doesn't match in the where() collection clause (doing a 'where' on anything in the attributes section seems to work as expected).

Anyway - my brain has possibly melted and I'm doing something really, really dim ;-) Anyone care to point at my glaring mistake and laugh? ;-)

Edit Your Profile
Update

Want to change your profile photo? We pull from gravatar.com.