Blog d'un développeur multi-support

[DIM] pour les intimes :)

APE Project – Mysql

Bonjour, j’ai eu un souci sur APE avec Mysql et comme je suis fier de ma solution je vous la propose :

Le souci c’est quand vous faites une requête SQL qui peut retourner des valeurs null dans vos colonnes, ben ça plante. Vous avez l’erreur « segmentation fault« . Normallement l’erreur devrait être corriger dans les prochaines versions d’APE mais en attendant voici le fix.

La fonction IFNULL de Mysql !

1
SELECT IFNULL(champ1, 0) as champ1, IFNULL(champ2, 0) as champ2 FROM matable

Et ouais, ça suffit à contourner le bug. Vous aurez des 0 au lieu de la valeur null, à vous d’adapter votre code en fonction !

Simple & court !

Aucun tag pour cet article.

APE Project – Présentation

Depuis quelques semaines je travaille sur la création d’un chat conçu sur APE Project (http://www.ape-project.org/ajax-push.html).

Pour faire simple c’est un serveur temps réel conçu pour fonctionner simplement avec du Javascript. En gros on code le serveur et le client directement en Javascript, le moteur se chargeant de transformer notre code serveur en instruction C. Du coup ça pulse et c’est léger.

En fait tout le fonctionnement est à base d’événement, comme on pourrait le faire en Flash avec Red5 ou autre. C’est à dire que le serveur envoie des évent (appelé raw), le client les reçoit, en renvoie – on peut créer nos propres évènements (appelé commande).

Le système est souple et au final on n’a pas besoin de serveur Flash ou de client Flash pour des besoins simple (comme un tchat). Je vous l’accorde, les serveurs Flash son bien plus complet (vidéo notamment), mais pour ce genre de besoin,pas la peine de prendre le marteau pour écraser la mouche.

Au final il est assez simple a prendre en main bien qu’il faut avoir le déclic à un moment pour synthétiser toute leur doc assez disparate. En effet la doc est sur le google group, le wiki, sur une page doc, sur les channels IRC .. Bref pas évident de s’y retrouver au début.

Loin de l’idée de faire des tutoriels pour le prendre en main, mais je vais essayer de faire des articles sur des points précis concernant des fonctionnalités que j’ai développé et des soucis que j’ai rencontré.

Tags : , ,

Symfony 1.2, behavior doctrine en actions

J’ai (re)découvert un truc vraiment sympathique au boulot c’est le système de behavior doctrine intégré à .

Hein ? Mais à quoi ça sert ?

Ce que j’en retiens c’est que cela peut permettre d’automatiser certaines actions (répétitives) à l’enregistrement en base, et donc d’enrichir son modèle et deux coup de cuillère à pot.

Prenons un exemple, vous devez faire un site basé sur la créations de contenus par vos utilisateurs. Ils peuvent écrire des billets, commenter, s’envoyer des messages privés, gérer un annuaire .. bref un site où l’on doit quasiment tout relié à un utilisateur. Chaques tables auraient donc au moins un « user_id » comme clée étrangère ce qui implique dans vos actions d’associer l’utilisateur courant à l’objet pour le sauvegarder .. et ce pour chaque table … lourd non ?

Hé bien grâce aux behaviors vous pouvez sortir ce comportement générique dans des classes et avec seulement de la configuration au niveau de votre schéma, vous pouvez associer ce comportement à n’importe quel table. L’exemple que j’ai pris est tiré du behavior « Signable » du plugin sfDoctrineActAsSignablePlugin.

Configuration

1
2
3
4
5
6
7
8
9
Item:
  actAs:
    Signable:
  columns:
    id:
      type:             integer
      primary:          true
      autoincrement:    true
    champ1:             string(255

Comment ça marche ?

Donc si on résume, il faut dire à Doctrineque l’on va rajouter des colonnes .. et que l’on veut être prévénu lors de l’insertion en base pour associé nos actions. Donc avec seulement 2 classes, une de définition et une d’écoute, on peut s’en sortir et crée notre behavior.

Lors de la configuration, en rajoutant « actAs : Signable », Doctrine va chercher une classe de définition qui ira  étendre une classe Doctrine_Template. Par convention il ira chercher une classe nommé Doctrine_Template_Signable. Le rôle de cette classe est de déclarer ses colonnes et de rajouter une écoute, un listener, vers l’autre classe d’actions.

Pour mon exemple, je vais volontairement raccourcir les classes du sfDoctrineActAsSignablePlugin et prendre pour acquis que vos utilisateurs sont gérés via sfGuardDoctrinePlugin.

Doctrine_Template

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Doctrine_Template_Signable extends Doctrine_Template {
 
  // Définitions des relations
  public function setUp() {
  // Bim rajoute une clée étrangère sur sfGuard
  $this->hasOne('sfGuardUser as Author', array(
            'local' => 'created_by',
            'foreign' => 'id'
            )
            );
  }
 
 public function setTableDefinition() {
 
  // Bim une colonne en plus
  $this->hasColumn('created_by', 'integer', 4, array(
          'type' => 'integer',
          'length' => '4',
     ));
 
  // Lien avec notre 2eme classe .. on passe le nom de la colonnette rajouté
  $this->addListener(new Doctrine_Template_Listener_Signable('created_by));
  }
}

Là pour l’exemple aucune configuration au niveau du schéma n’est possible mais c’est facile à rajouter via d’un tableau d’options et le constructeur suivant :

1
2
3
  public function __construct(array $options = array()) {
    $this->_options = Doctrine_Lib::arrayDeepMerge($this->_options, $options);
  }

Doctrine_Template_Listener

Nous avons vu que notre Template rajoute un listener vers notre 2e classe en lui passant la colonne à surveiller (dans la vrai vie, un tableau d’options ..). Le rôle de notre listener de pouvoir agir avant/après l’insertion/édition d’un objet .. facile :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Doctrine_Template_Listener_Signable extends Doctrine_Record_Listener {
 
  protected $_colonette = "created_by";
 
  public function __construct($colonne) {
    $this->_colonette = $colonne;
  }
 
  public function preInsert(Doctrine_Event $event) {
      $createdName = $this->_colonette;
 
      // recupère l'objet appellant :
      $objet = $event->getInvoker();
 
      // Affectation de valeur
       $objet->$createdName = $this->getUserId();
  }
 
  public function getUserId() {
     // Echappe le mode cli
     if (0 != strncasecmp(PHP_SAPI, 'cli', 3)) {
       // L'user courant
       return sfContext::getInstance()->getUser()->getAttribute('user_id', null, 'sfGuardSecurityUser');
     } else {
      return null;
     }
  }
 
  public function preUpdate(Doctrine_Event $event) {
  }
 
  public function postUpdate(Doctrine_Event $event) {
  }
 
  public function postInsert(Doctrine_Event $event) {
  }
 
  // A tester : public function Delete(Doctrine_Event $event) ..
}

Vous n’avez plus qu’a rebuilder votre model et magie ça doit marcher !!

Vu que l’on a fait une relation de type One-to-many sur sfGuard vous pouvez accéder à l’utilisateur sfGuard via la propriété Author sur n’importr quel table marqué comme « Signable »

1
  echo $objet->Author->id;

Voilà .. simple au final non ? Ah vous de créez le votre, :p

Comme on dirait au boulot « Amaaziiiing !! »

Tags : , , , ,

Symfony 1.2 & Personnalisation des pages 404 & 500

Voici un petit tips sorti tout droit de jobeet pour personnaliser ses pages 404 & 500 sur Symfony 1.2. C’est bête comme chou comme truc mais faut le savoir quoi.

Page 404 :

Pour la page 404 c’est dans le fichier settings de votre application
/apps/front/config/setting.yml

Il faut tout simplement rajouter ces deux directives

1
2
3
all:
  error_404_module: home
  error_404_action: error404

Du coup quand vous aurez une erreur 404 cela sera votre page qui sera affiché, vous pourrez donc dans votre action vous ajoutez une petite ligne pour vous envoyer un mail quand y a un souci. (Le plugin nahoMail est vraiment top d’ailleurs). Du monitoring pas cher quoi.

Page 500 :

Vous croyez qu’il aurait fallu mettre

1
2
3
all:   
   error_500_module: home 
   error_500_action: error500

Et bien ça ne marche pas du tout comme ça. Pour personnaliser cette page vous devez placer un fichier « error.html. » dans le répertoire « apps/front/config/error » (crée le au besoin). Et c’est tout.

Mais du coup voilà, nous ne sommes pas dans une action .. donc cette page n’est pas inclu dans votre layout, on ne peut non plus utiliser les classes .. et oui la page d’erreur 500 est complétement statique. Adieu le monitoring pour cette page.

Si vous connaissez un moyen de customiser cette page et de pouvoir profiter du en même temps je suis preneur :p

Sur ceux, à bientôt pour de nouvelles Symfony

Tags : , ,

Retour de vacances

Me voici de retour,

Je préviens que ce blog risque de ne pas être mis à jour pendant encore un moment. J’emménage à Lyon, je change de job, et je n’aurais plus de mac pour développez sur tout de suite. Donc pour les lecteurs «  » du blog désolé mais c’est chômage technique en vue.

C’est con, j’aurais bien aimer tester la réalité augmenté sur iphone grâce à http://code.google.com/p/iphonearkit. L’avez vous tester cette libraire vous ? Mais bon, je n’ai pas d’iphone 3GS non plus. D’ailleurs si vous avez un mac, un iphone 3GS que vous voulez me donner, y a pas de souci je prend :p

Petite annonce iphone : Je suis à la recherche de dev iphone sur Lyon, débutant ou confirmé. N’hesitez pas à vous signaler par mail, je ne mord pas.

Par contre, pour ceux qui viennent pour du PHP et pour Symfony vont être content. Mon nouveau job m’en fera faire 8h par jour, je parie que je vais découvrir pleins de trucs que je posterais sur ce blog. :p

Adieu objective-c, welcome . (La tendance est de faire l’inverse, mais je ne suis pas comme les autres ;p)

Tags : , ,

Nouveauté du site

Comme c’est à la mode, j’ai succombé à FriendFeed. J’ai donc remodelé ce blog en fonction.

A la place de l’encadré « ma veille quotidienne » où je vous donnais tous mes flux que je suivais et qui au final n’était pas très intéressant je l’ai remplacé par mon flux d’activité delicious/google reader. Il y aura donc en temps réel une sélection d’article qui me semble intéressant.

A propos des commentaires de mes articles je laisse le système par défaut, mais je donne en plus la possibilité de voir les réactions sur FriendFeed et si vous avez un compte vous pourrez directement réagir à partir de la page. Peut être qu’avec deux systèmes il y aura deux fois plus d’activité (ou pas ^^).

A oui, et mon compte FriendFeed est : http://friendfeed.com/guillaumechave. Pour les raleurs qui diront « ouais mais tu connais personne la looze », je leur dirait « je viens de m’inscrire et je t’emm*** » :p

Image representing FriendFeed as depicted in C...
Image via CrunchBase
Tags :

Débuter sur le développement iPhone

Salut,
Il m’est arrivé plusieurs fois qu’on me demande ce qu’il faut pour bien débuter sur iPhone. La question est simple, la réponse un peu moins. Je vais commencer par le plus simple, le matériel.

Matériel :

  • un Mac intel. Désolé mais vos vieux mac à la cave ne marcheront pas.
  • un de test. Le simulateur ne suffit pas.
  • une licence de développeur Apple. (Pas bien cher, 70€ je crois ..). Ceux qui disent  « Mais je jailbreak j’envoie mes appli en SSH et fuck Apple » je leur répond « Vous vous faites bien chier. » Et les solutions pour auto signer son code pour l’envoyer « comme en vrai » c’est pas trop la joie (faut refaire les manips pour chaque projets ..)

Sinon pour développer sur PC (windows notamment) sachez qu’on peut compiler des applis et se les envoyer en SSH etc. C’est faisable, mais alors quel perte de temps et vous verrez dans la suite de l’article qu’on y gagne pas tant que ça.

Logiciels :

  • Xcode le seul et unique IDE sympathique. Il auto-complète un peu, permet de compiler directement sur le téléphone sans prise de tête, fourni un debugger pas à pas.
  • Interface Builder. Ça c’est le truc tape à l’oeil  qu’Apple met en avant. C’est pour construire les écrans et relier les éléments graphiques à leurs représentations « code ». C’est super pratique et beaucoup plus ergonomique que de le faire sur Android :
    // Lie les champs graphiques à des champs codes
    EditText login = (EditText) findViewById(R.id.login);
  • Instruments. Super pratique pour voir l’état en temps réel de l’iphone : consommation CPU, RAM, allocations d’objets etc. C’est avec ce genre d’outils que tu te dis « en fait je ne sais pas coder léger »

Donc on voit bien que même s’il existe des solutions pour compiler sur PC, les « toolchain iphone » c’est quand même dommage de se séparer de ces logiciels. Encore que pour Xcode eclipse doit pouvoir suffir, les deux autres logiciels n’ont pas l’air d’avoir d’équivalent.

Et puis la finalité de développer sur iPhone c’est bien d’avoir son quart d’heure de gloire sur l’appStore non ? Alors autant commencer bien et dans la légalité. Car si Apple découvre que vous n’avez pas utilisé ses outils, que votre appli est dispo en jailbreak etc .. ben c’est foutu après.

Langage de programmation

Je suis passé par 3 phases quand j’ai commencé à programmer en objective-c.

  • Déroutant au début (retain une variable ? Kesako ?)
  • a l’air d’avoir des mécanismes complexes (le parsage d’XML est chelou quand on vient du web /as3 etc)
  • Pratique et puissant quand on comprend les mécanismes par delegate, que l’on joue avec les threads, que l’on crée ses propres classes outils (comme pour ma classe de requete http)

Mais comment apprendre ce langage ? la réponse est simple : dans la documentation.

Documentation et

La documentation et les guides Apple sont bien pratiques pour appréhender le langage et les mécanismes.

Cependant pour appréhender Interface Builder et sa relation avec le code c’est pas trop ça. Je conseille les tutos d‘ipup.fr qui ont pas mal d’images et surtout que c’est français.

Sinon pour plus de liens, je vous conseille toujours les liens de mon précédent article « créer des applications iphone » et mon flux delicious :

ps : Si vous voulez suivre mes « découvertes » iphone,  mon flux delicious est constamment mis à jour ! http://delicious.com/onishinji/iphone

Tags : ,

iPhone & NSTimer

Salut,

Les NSTimers sont bien cool et en général ça ne pose aucun souci à les utiliser. J’ai bien dit en général. J’ai eu un souci avec ce matin…vraiment étrange.

Sur un projet, j’en utilise un pour déclencher une méthode dans XX secondes une fois seulement. Ça marche impeccable. Sur un nouveau projet, je réutilise le même mais en faisant varier un paramètre « repeats » à YES. Et bien sur, ça ne marchait plus.

Voici un timer qui déclenche une méthode une seule fois :

1
2
3
4
5
6
7
8
-(void)blabla
{
	[NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(test:) userInfo:nil repeats:NO];
}
-(void)test:(NSTimer*)timer
{
	NSLog(@"je suis appelé 1 fois");
}

Un timer qui se déclenche une méthode en boucle, techniquement il faudrait juste dire « repeats:YES » mais ca n’a pas marché dans mon cas. Le timer n’était jamais « fired » :p (je m’essaie à l’anglais)

1
2
3
4
5
6
7
8
-(void)blabla
{
	[NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(test:) userInfo:nil repeats:YES];
}
-(void)test:(NSTimer*)timer
{
	NSLog(@"je suis appelé en boucle c'est la fête.");
}

Donc voici ce que j’ai utilisé pour que ça marche. J’ai forcé le démarrage du timer en boucle.

1
2
3
4
5
6
7
8
9
10
-(void)blabla
{
	NSTimer * timer = [NSTimer timerWithTimeInterval: 1 target: self selector: @selector(test:) userInfo: nil repeats: YES];
 
	[[NSRunLoop mainRunLoop] addTimer: timer forMode: NSDefaultRunLoopMode];
}
-(void)test:(NSTimer*)timer
{
	NSLog(@"je suis appelé en boucle c'est la fête.");
}

Voilà voilà

Tags : ,

iPhone & Trucs et Astuces

Bonjour tout le monde, encore de l’ .. et ouais j’aime bien faire des petits exemples :p

Cette fois ci à la demande non général de Sébastien H. voici quelques éléments de que j’utilise dans mes applications.  Donc voici ce qu’il y a dans cet exemple :

  • Comment créer et utiliser les préférences utilisateurs à travers l’objet NSUserDefaults et le fichier settings.bundle :p
  • Comment créer une vue modal. Vous savez ce genre d’écrans qui arrivent par le bas de l’application et qui repartent ensuite.
  • Je refait aussi un petit rappel sur les delegate iphone pour la vue modal.
  • Comment créer et utiliser le fameux menu d’actions à la façon safari pour permettre de fournir des boutons qui arrivent aussi par le bas de l’application (UIActionSheet)
  • Comment ouvrir d’autres applications installées sur l’iphone grâce à la méthode [UIApplication sharedApplication] :p

On m’a dit qu’il manquait un peu d’images, voici des screenshoots de l’application d’exemple :

Le design est assez simple ;p

Et n’oubliez pas de télécharger le projet Xcode de cet exemple

Tags : , , , ,