zefman

Developer at theunit.co.uk

Experience

12,350

7 Best Reply Awards

  • Member Since 4 Years Ago
  • 71 Lessons Completed
  • 1 Favorite

8th October, 2015

zefman left a reply on Broadcasting Event To Specific Client • 2 years ago

@ukietech sweet will have a look. Interested to see how you have used JWTs. I had researched them for this purpose but never got round to trying anything out.

30th September, 2015

zefman left a reply on Broadcasting Event To Specific Client • 2 years ago

Hi @ukietech sorry for the slow reply, been busy.

So in Laravel I do something like this:

    $redis = \RedisL5::connection();
        $redis->publish( 'messaging', json_encode( [
            'conversation_id' => $conversation->id,
            'participants'    => $participants,
            'message'         => $message
        ] ) );

Where participants is a list of user ids that I want the message to go to.

Then in node I do something like this:

// Subscribe to the relevant redis channels
redisClient.subscribe( 'messaging' );

// On recieving a message from one of the channels we subscribed too.
// Note 'message' is just redis's term for recieving something from a 
// subscribed channel. This is note a message sent by a user on bfc
redisClient.on( 'message', function( channel, data ) {

    data = JSON.parse( data );

    // Check to see whether this user should recieve this message
    if ( data.participants.indexOf( client.laravelSession[ userIdKey ] ) > -1 ) {

        // Check the message is not from the connected user
        if ( data.message.user_id != client.laravelSession[ userIdKey ] ) {
            client.emit( channel, data );
        }

    }

} );

Basically it looks to see if the connected client is in the participants lists, if they are it emits the message to them. Is that what you were after?

25th September, 2015

zefman left a reply on Broadcasting Event To Specific Client • 2 years ago

@ukietech The code there doesn't do any of the relaying of websocket data. It just retrieves the session so you know which user you are dealing with. Because you then have the user id it is then easy to broadcast messages intended for one user to that user. You just need to send a userid along with the event you pass to redis

3rd July, 2015

zefman left a reply on Pivot Table Problem • 3 years ago

aasasd ada sdas dasdas dasd as dasd asdasd asd

26th June, 2015

zefman left a reply on Broadcasting Event To Specific Client • 3 years ago

Great!!! Glad I could help, I had the eureka moment too the first time I got it to work!

zefman left a reply on Broadcasting Event To Specific Client • 3 years ago

Hmm I'm not sure then I'm afraid. This setup is working for us. If it is the same domain as your main laravel app the session cookie should be sent with the initial request, there must be something else wrong.

zefman left a reply on Broadcasting Event To Specific Client • 3 years ago

The port number shouldn't matter, you can leave that as what you had before. Its just the domain thats important. So if you visit your laravel site are you using the address socket.dev?

zefman left a reply on Broadcasting Event To Specific Client • 3 years ago

yeah thats it. Any luck?

zefman left a reply on Broadcasting Event To Specific Client • 3 years ago

Is your socket.io running at a different address/ip? It will only send the laravel cookie if you connect to it using the same domain. So if your site is example.com your node server will need to be at example.com: 8080 or whatever port it is you have it running on. If it is on the same domain it should send along the laravel cookie

24th June, 2015

zefman left a reply on Broadcasting Event To Specific Client • 3 years ago

Hi sorry for the slow reply, been very busy. This is what we have:

var cookieKey = 'login_82e5d2c56bdd0811318f0cf078b78bfc';

// On websocket connections
io.listen( server ).on( 'connection', function( client ) {

    const redisClient = redis.createClient();
    // Select the correct redis db
    redisClient.select( process.env.REDIS_DB, function() {});
    logger.info( 'Connected and listening to redis db ' + process.env.REDIS_DB + '.....' );

    // Get the laravel cookie
    var cookies        = cookie.parse( client.handshake.headers.cookie );
    var laravelSession = cookies.laravel_session;
    var sessionId      = 'laravel:' + getSessionIdFromLaravelCookie( laravelSession );
    var userId;

    // Find the user id
    redisClient.get( sessionId, function( err, session ) {
        try {
            client.laravelSession = PHPUnserialize.unserialize( PHPUnserialize.unserialize( session ) );
            connectedUsers[ client.laravelSession[ cookieKey ] ] = client;
        }
        catch ( err ) {
            logger.info( 'Error unserializing session!', err );
        }

        if ( client.laravelSession[ cookieKey ] ) {
            logger.info( 'User connected: ' + client.laravelSession[ cookieKey ] );
            logger.info( 'Total connected: ' + _.keys( connectedUsers ).length );
            userId = client.laravelSession[ cookieKey ];
        }

    } );

} );

23rd June, 2015

zefman left a reply on Broadcasting Event To Specific Client • 3 years ago

Oh i forgot you will need to install these dependencies of the node mycrypt library:

 apt-get install libmcrypt4 libmcrypt-dev

zefman left a reply on Broadcasting Event To Specific Client • 3 years ago

Hi,

We successfully did this before the new event broadcasting stuff was added. You are on the right track. You need to decrypt their cookie and then use it to retrieve the user's session, this is quite easy if you also use redis for sessions.

We have this code, which I think I got from a blog post somewhere, unfortuanatrly i can't find it now!


/**
 * Helper function to return ASCII code of character
 * @param  [string] string
 * @return [ascii code]
 */
function ord( string ) {
    return string.charCodeAt( 0 );
}

/**
 * This function retrieves the laravel session stored in redis
 * from a cookie
 * @param  [cookie] cookie
 * @return session
 */
function getSessionIdFromLaravelCookie( cookie ) {

    var cookie = JSON.parse( new Buffer( cookie, 'base64' ) );

    var iv     = new Buffer( cookie.iv, 'base64' );
    var value  = new Buffer( cookie.value, 'base64' );
    var key    = 'dd4u1wm2rVi82s6eOI8sTRzaWomob58x'; // laravel app key

    var rijCbc = new MCrypt( 'rijndael-128', 'cbc' );
    rijCbc.open( key, iv ); // it's very important to pass iv argument!

    var decrypted = rijCbc.decrypt( value ).toString();

    var len = decrypted.length - 1;
    var pad = ord( decrypted.charAt( len ) );

    var sessionId = PHPUnserialize.unserialize( decrypted.substr( 0, decrypted.length - pad ) );

    return sessionId;
}

After you have done this you should be able to get their use id and it should be fairly straight forward from there.

11th May, 2015

zefman left a reply on Socket.io And Laravel Cant Connect To Socket • 3 years ago

Try changing the line that starts the node server to this:

server.listen( port, '192.168.10.10' );

and then on your frontend

var socket = io('http://192.168.10.10:3000');

Then it should work if you start the node server on homestead

6th May, 2015

zefman left a reply on Forge/git Error When Trying To Commit • 3 years ago

It seems as though you have edited files live on the server so git is worried you will overwrite them. Also for some reason your vendor folder is tracked it shouldn't be and should be added to your git ignore.

After adding the vendor folder to your git ignore, cd into your project directory then: ''' git rm --cached vendor ''' then commit the changes and push to your remote repository. This will stop tracking the vendor folder.

Now log into your server, cd into your project folder, and run: ''' git stash ''' This will temporarily clear those changes and you should be able to deploy again with forge.

9th April, 2015

zefman left a reply on Hoa\WebSocket With Laravel 5 Projects - Push Notifications • 3 years ago

I implemented realtime messaging in a Laravel app recently using web sockets and found the best, way to interact between the socket server and the Laravel app was to use a shared redis database.

In my case I used node for the websocket server but it would work the same either way. In Laravel I do something like,

    $redis = \RedisL5::connection();
        $redis->publish( 'messaging', json_encode( [
            'conversation_id' => $conversation->id,
            'participants'    => $participants,
            'message'         => $message
        ] ) );

Then on websocket server you can subscribe to the redis channel, and push the messages, notifications or whatever you like on the clients. In node its something like this:

    // Subscribe to the redis messaging channel
        redisClient.subscribe( 'messaging', 'conversation' );

        redisClient.on( 'message', function( channel, data ) {

            data = JSON.parse( data );

        client.emit( channel, data );
    } );

19th February, 2015

zefman left a reply on Php Artisan Db:seed • 3 years ago

try 'composer dump-autoload" and "php artisan clear-compiled"

14th February, 2015

zefman left a reply on Creating Push Notifications • 3 years ago

I have just done this to enable realtime chat and notifications in a Laravel app. We have used socket.io for the web sockets, and then we have connected up laravel and nodes using a shared reds database. Its then super easy to push messages from laravel. We do something like this:

$redis = \Redis::connection();
$redis->publish(  'conversation',  json_encode( [
    'message' => 'Hello,
    'participants' => $participants
] ) );

Then in node we subscribe to reds for updates like so:

// Subscribe to the conversation channel
redisClient.subscribe( 'conversation' );

// Relay the message on the user
redisClient.on( 'message', function( channel, data ) {
    socket.emit( channel, data );
}

That is a simplified version obviously a lot of other things go on to but thats the basics.

We also use redis for sessions so found it useful to access these through node, this allowed us to authenticate and identify which user was connecting to each web socket as well.

6th February, 2015

zefman left a reply on Upgrading To L5 And Getting "Class Not Found" On Composer Update • 3 years ago

I had this issue as well. I got around it by manually deleting the compiled files in storage>framework. The issue was the php artisan clear-compiled was failing before it could actually get rid of the files. It could be the same issue for you :)

3rd February, 2015

zefman left a reply on Problems With Auth::user() • 3 years ago

Thanks @pmall that was it! The correct user model was not set in config/auth.php.

Thanks for your help :)

zefman left a reply on Problems With Auth::user() • 3 years ago

@pmall Thanks that was it, the correct user model wasn't set in config/auth.php

Thanks for your help!

zefman left a reply on Problems With Auth::user() • 3 years ago

Thanks but as I said, this was working before running composer update, so I am pretty sure the relation is not the issue, and also if I load a user manually the relations work fine. This is how the comments relation is defined in my user model:

    /**
     * Get the users comments
     * @return Collection
     */
    public function comments()
    {
        return $this->hasMany('BigFanClub\Models\Comment');
    }

dd( Auth::user() ) results in this which looks ok to me:

User {#247 ▼
  #table: "users"
  #fillable: array:3 [▼
    0 => "name"
    1 => "email"
    2 => "password"
  ]
  #hidden: array:2 [▼
    0 => "password"
    1 => "remember_token"
  ]
  #connection: null
  #primaryKey: "id"
  #perPage: 15
  +incrementing: true
  +timestamps: true
  #attributes: array:8 [▼
    "id" => 680
    "email" => "protractor@protractor.com"
    "password" => "$2y$10$PbYYE20QNlUBlVHs1QR3FemqlH5D2WeYHYy1kTaDN.ZOplW6vrrO2"
    "confirmed" => 1
    "confirmation_code" => null
    "remember_token" => "7KraYlUdBX8qHO2umiRhxuolUV0XFIDzqv1KrcdS4WRK8bT0xc1JyyjgXiAt"
    "created_at" => "2015-01-15 10:46:42"
    "updated_at" => "2015-02-03 12:01:36"
  ]
  #original: array:8 [▼
    "id" => 680
    "email" => "protractor@protractor.com"
    "password" => "$2y$10$PbYYE20QNlUBlVHs1QR3FemqlH5D2WeYHYy1kTaDN.ZOplW6vrrO2"
    "confirmed" => 1
    "confirmation_code" => null
    "remember_token" => "7KraYlUdBX8qHO2umiRhxuolUV0XFIDzqv1KrcdS4WRK8bT0xc1JyyjgXiAt"
    "created_at" => "2015-01-15 10:46:42"
    "updated_at" => "2015-02-03 12:01:36"
  ]
  #relations: []
  #visible: []
  #appends: []
  #guarded: array:1 [▶]
  #dates: []
  #casts: []
  #touches: []
  #observables: []
  #with: []
  #morphClass: null
  +exists: true
}

Maybe a clear demonstration of the issue:

// Results in Call to undefined method Illuminate\Database\Query\Builder::profile()
$user = Auth::user()->load( 'profile );

// Works perfectly
$user = User::find(1)->load( 'profile );

zefman started a new conversation Problems With Auth::user() • 3 years ago

Hello everyone.

So today I have ran composer update to bring a project up to the latest version of Laravel 5, almost everything is fine, but I am having issues with Auth::user() after updating.

In a number of places in the app I use Auth::user() to return the currently logged in user, the problem is, after this most recent update whenever I then go to try and load relations on the returned user object I get an error like:

Call to undefined method Illuminate\Database\Query\Builder::comments()

For example the following code causes this error:

$user = Auth:;user();
$user->load( 'profile.media', 'roles' );

likewise does this:

$user = \Auth::user();
$comments = $user->comments;

This was all working fine before so I am not sure whats wrong. Interestingly if I use the id from the user returned by Auth to again find the user like:

$user = User::find( Auth::user()->id );
$comments = $user->comments;

It works. Anyone got any ideas?

Cheers

21st January, 2015

zefman left a reply on Modal Relationships • 3 years ago

No problem. You just surround it with ```

zefman left a reply on Modal Relationships • 3 years ago

You could use the hasManyThrough relation in your company model:

public function contractors()
{
     return $this->hasManyThrough( 'Contractors', 'Projects' );
}

20th January, 2015

zefman left a reply on SSH Port Forwarding Failed • 3 years ago

Hmm thats a strange one I have about 10 long running Forge servers running and have never seen this. A quick google has revealed that this can be caused by not closing ssh sessions correctly. Maybe that is what is happening.

zefman left a reply on Validator - Passing Through Parameter • 3 years ago

In your Validator class add this:

protected $company_id;
function __construct()
{
    $this->company->id = Auth::user()->company->id;
}

protected $rules = [
    'name'      =>    'required|unique:inventory_items,name,NULL,id,company_id, ' . $this->company_id
];

16th January, 2015

zefman left a reply on Ionic & Laravel • 3 years ago

No problem, yes you can still use CRSF filters although you have to do a little bit more work to get it to work. This answer on stackoverflow is a pretty good solution: http://stackoverflow.com/a/23760366

You are probably going to want an ssl certificate to make sure your api is secure. Just make good use of angular resource which makes consuming with apis super easy, and try and keep your json responses from laravel consistent.

15th January, 2015

zefman left a reply on Ionic & Laravel • 3 years ago

Yes I have, only as an experiment though. Although it is looking likely that we will be developing a production app using ionic and laravel in the future.

We developed our api in laravel, and then hocked an ionic project into the api using angular resource or http. So they are essentially to separate projects, the ionic app just consumes the api.

zefman left a reply on Eloquent Performance Improvements -- Studly Caps • 3 years ago

Ah ok interesting. I'm excited to see what performance difference this little change might make.

14th January, 2015

zefman left a reply on Eloquent Performance Improvements -- Studly Caps • 3 years ago

@anzze I didn't notice that cache, strange its not being used here. Do you reckon its just an oversight? Yes I was thinking about a pull request, should be easy now that I can see that cache is already there.

@thepsion5 Yeah I would love to drop eloquent, but unfortunately there are quite a lot of relations going on. Until the performance becomes an issue I think the benefits outweigh the negatives.

zefman left a reply on Eloquent Performance Improvements -- Studly Caps • 3 years ago

Yes I know Eloquent is not ideal in this situation. By data heavy I mean the app is aggregating a feed built up of a number of different models and their relations. Performance wise it is still ok at the even on a 5$ a month digital ocean testing server.

If I get chance I'll try with Doctrine too, will be interesting to compare.

zefman started a new conversation Eloquent Performance Improvements -- Studly Caps • 3 years ago

Hello,

So I have recently been experimenting blackfire.io the profiling tool on a fairly data heavy app, and noticed that there were thousands of calls to Illuminate\Support\Str::studly which is converts a string into studly case. This is obviously pretty heavy due to the string transformations.

After a little digging I found this is used in an Eloquent Model's hasGetMutator, a function that is called whenever an attribute from a model is retrieved to check to see if you have created a mutator.

        /**
     * Determine if a get mutator exists for an attribute.
     *
     * @param  string  $key
     * @return bool
     */
    public function hasGetMutator($key)
    {
        return method_exists($this, 'get'.studly_case($key).'Attribute');
    }

In the app I'm profiling we never use get mutators ( all models pass through a dedicated transformer at some point ) so this is a complete waste. Solution extend the standard eloquent model and override the hasGetMutator method like so:

public function hasGetMutator($key)
{
    return false;
}

Doing just this has shaved about 400ms of my response times on the most data heavy parts of the app, sometime more.

Can anyone see any possible unexpected side effects from doing this? Maybe it would be a good idea to be able to set a flag on the eloquent model to enable and disable this feature.

9th January, 2015

zefman left a reply on L5 With Angularjs, Routing Problems • 3 years ago

Great glad i could help :)

zefman left a reply on L5 With Angularjs, Routing Problems • 3 years ago

No that is a controller function, but you could just do something like this in your routes file:

Route::any('{path?}', function()
{
    return view("index");
})->where("path", ".+");

zefman left a reply on L5 With Angularjs, Routing Problems • 3 years ago

Basically I think his problem is that he wants angular to handle the routing of his application. To do this he needs requests to pass through laravel's router so requires a catch all route that just loads the main angular file.

zefman left a reply on L5 With Angularjs, Routing Problems • 3 years ago

I was using this when annotations were still around in laravel 5:

        /**
     * Redirects any other unregistered routes back to the main
     * angular template so angular can deal with them
     *
     * @Get( "{path?}", as="catch.all" )
     * @Where({"path": ".+"})
     *
     * @return Response
     */
    public function catchOtherRoutes()
    {
        return view("index");
    }

5th January, 2015

zefman left a reply on Page Slugs And Nesting • 3 years ago

I'de be interested in this too, its a tricky topic!

17th December, 2014

zefman left a reply on [Tip] Vagrant VM Manager (OS X/Win) • 3 years ago

This is super handy :)

12th December, 2014

zefman left a reply on Modular Way To Structure Js Files • 3 years ago

If you are using angular you should check out this: https://github.com/johnpapa/angularjs-styleguide

Even if you are not there are some great best practices that can be taken away for general js dev :)

11th December, 2014

zefman left a reply on File::isFile Returning False (but I Know It's There!!!) • 3 years ago

Thats very strange the file inside appears to be the temporary file that php created when you upload a file. Have you dumped your filepath variable just before you do the move to check everyhting there looks ok?

zefman left a reply on How Can I Do Multiple Inserts In An API Store() And Not Abuse Single Responsibility • 3 years ago

Are you using Laravel 5? if you are use a form request to check whether the email is unique. Thats moves the validation outside of your controller. Or if you want to just do it in the controller like @lonut suggested do this:

if( !empty( User::where('email', Input::get('email') )->first() ) )

Also are you storing the email twice? If a farmer belongs to a user there is no need to store the email on both tables.

10th December, 2014

zefman left a reply on Scaling With Laravel And Forge • 3 years ago

@getstartify yes I was expecting a slight dip in average response times overall, but didn't really see this with a multi server set up on digital ocean. I was able to handle more requests, but not as many more as I was expecting.

I actually have the results of this testing in a rather messy spreadsheet here if you are interested: https://docs.google.com/spreadsheets/d/14vcovx322FeGwfW8i6G2CctMGaRoeiPiOc2Ya3rmt0w/edit?usp=sharing

I also had a quick play with hhvm and saw some very impressive increases in performance in some areas, but decreases in others.

Interestingly cpu was always the limiting factor.

zefman left a reply on Scaling With Laravel And Forge • 3 years ago

Another +1 here. I have recently been experimenting on different multiple server setups using forge, and while I have found it relatively easy to split into multiple instances working off a shared db server, I haven't always seen the performance gains I would expect.

Would love to see something along these lines, and maybe app optimisation in general.

zefman left a reply on I Need Some Advices About Small Share Files Application • 3 years ago

Not quite sure what you are asking but sounds like you would need a files table that holds info about each file, including the user who uploaded it, who can download it etc etc

zefman left a reply on Multiple Languages • 3 years ago

Ok so I am just trying to understand what is happening here, in the foreach ( $language as $lang ) bit are you trying to output one input field for each language?

zefman left a reply on Extra Relation In Polymorphic Many To Many • 3 years ago

Yeah unfortunately I don't think there is a way to do this with eloquent.

zefman left a reply on Multiple Languages • 3 years ago

Could you maybe post some code to give us a better idea of what is going wrong?

zefman left a reply on Extra Relation In Polymorphic Many To Many • 3 years ago

You can easily store the user_id on the pivot table, but I don't think retrieving it as an eloquent relation is possible.

Do you know how to store and retrieve extra attributes on the pivot table?

9th December, 2014

zefman left a reply on Deployment Scripts • 3 years ago

You might also want to add "php artisan optimize" :)

zefman left a reply on Updating Different Parts Of View Using Ajax Calls ( Big Response Time ) • 3 years ago

Ah I see @Aktara the problem is that you are making lots of requests at once. 150ms with no db queries is pretty slow though, is this in vagrant, or on a production server? That sounds to me as though there is another problem.

Have you thought about trying to combine the ajax calls into one request?

@CrtlAltDylan we usually just try to keep it relatively simple and use the remember functionality like this:

$users = Cache::remember('users', 10, function()
{
    return User::with('profile')->get();
});

That looks for the 'users' entry in the cache, if it is there its returned, if not it will fill the cache using the database ready for next time.

We also make heavy use of events to flush the cache at certain points.

Edit Your Profile
Update

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